def serialize(obj: Any, pyobjson_base_custom_subclasses: List[Type]) -> Any:
"""Recursive function to serialize custom Python objects into nested dictionaries for conversion to JSON.
Args:
obj (Any): Python object to serialize.
pyobjson_base_custom_subclasses (list[Type]): List of custom Python class subclasses.
Returns:
dict[str, Any]: Serializable dictionary.
"""
if type(obj) in pyobjson_base_custom_subclasses:
serializable_obj = {}
for att, val in unpack_custom_class_vars(obj, pyobjson_base_custom_subclasses).items():
if isinstance(val, dict):
att = f"collection:dict.{att}"
elif isinstance(val, (list, set, tuple, bytes, bytearray)):
att = f"collection:{derive_custom_object_key(val.__class__)}.{att}"
elif isinstance(val, Path):
att = f"path.{att}"
elif isinstance(val, Callable):
att = f"callable.{att}"
elif isinstance(val, datetime):
att = f"datetime.{att}"
serializable_obj[att] = serialize(val, pyobjson_base_custom_subclasses)
return {derive_custom_object_key(obj.__class__): serializable_obj}
elif isinstance(obj, dict):
return {k: serialize(v, pyobjson_base_custom_subclasses) for k, v in obj.items()}
elif isinstance(obj, (list, set, tuple)):
return [serialize(v, pyobjson_base_custom_subclasses) for v in obj]
elif isinstance(obj, (bytes, bytearray)):
return b64encode(obj).decode("utf-8")
elif isinstance(obj, Path):
return str(obj)
elif isinstance(obj, Callable):
return derive_custom_callable_value(obj)
elif isinstance(obj, datetime):
return obj.isoformat()
else:
return obj