[docs]defdefault(o:Any)->Union[Dict[str,Any],str]:r"""Customized JSON serializer. (1) Support internal dataclasses and components instance serialization by calling to_dict() method. (2) Support internal dataclasses class serialization by calling to_dict_class() method. (3) Any external instance if it has to_dict() method, it will be serialized. (4) All other objects will be serialized as {"type": type(o).__name__, "data": str(o)} """seralized_obj={}# 1. Handle the case like Component, DataClass where we have to_dict and to_dict_classobj_type=check_object(o)ifobj_type==ObjectTypes.CLASS:log.debug(f"Object {o} is a class with name {o.__name__}")ifhasattr(o,"to_dict_class")andcallable(getattr(o,"to_dict_class")):try:seralized_obj=o.to_dict_class()returnseralized_objexceptExceptionase:log.error(f"Error serializing object {o}: {e}")passelifobj_type==ObjectTypes.INSTANCE:log.debug(f"Object {o} is an instance of {o.__class__.__name__}")ifhasattr(o,"to_dict")andcallable(getattr(o,"to_dict")):try:seralized_obj=o.to_dict()returnseralized_objexceptExceptionase:log.error(f"Error serializing object {o}: {e}")pass# handle setelifisinstance(o,set):return{"type":type(o).__name__,"data":list(o)}else:return{"type":type(o).__name__,"data":str(o)}# raise NotImplementedError(# f"Object of type {o.__class__.__name__} is not JSON serializable: {o}"# )elifobj_type==ObjectTypes.TYPE:log.debug(f"Object {o} is a type of {o.__name__}")try:return{"type":type(o).__name__,"data":str(o)}exceptExceptionase:log.error(f"Object of type {o.__class__.__name__} is not JSON serializable: {str(e)}")passlog.debug("Fallback to serializing attributes who come from external libraries")# (2) Fallback to serializing attributes who come from external librariestry:return{"type":type(o).__name__,"data":str(o)}exceptExceptionase:raiseTypeError(f"Object of type {o.__class__.__name__} is not JSON serializable: {str(e)}")
[docs]defserialize(obj:Mapping[str,Any])->str:"""Serialize the object to a json string. Args: obj (Mapping[str, Any]): The object to be serialized. Returns: str: The serialized object in json format. """returnjson.dumps(obj,indent=4,default=default)
[docs]defdeserialize(data:str)->Any:"""Deserialize the JSON string back to an object."""returnjson.loads(data,object_hook=_deserialize_object_hook)
def_deserialize_object_hook(d:Dict[str,Any])->Any:"""Hook to deserialize objects based on their type."""if"type"indand"data"ind:class_name=d["type"]ifclass_name=="set":returnset(d["data"])# deseralize customized types# TODO: all customized data types need to be savedclass_type=EntityMapping.get(class_name)try:ifclass_type:returnclass_type.from_dict(d)exceptExceptionase:# default to the original objectlog.error(f"Error deserializing object {d}: {e}")passreturnd
[docs]defto_dict(obj:Any)->Dict[str,Any]:"""Convert the object to a dictionary. Args: obj (Any): The object to be converted. Returns: Dict[str, Any]: The dictionary representation of the object. """returnjson.loads(serialize(obj))