Recursive method to deserialize JSON into typed data structures for conversion to custom Python objects.
Parameters: |
-
json_data
(Any )
–
JSON data to be deserialized.
-
pyobjson_base_custom_subclasses_by_key
(dict[str, Type] )
–
Dictionary with snakecase strings of all subclasses of
PythonObjectJson as keys and subclasses as values.
|
Returns: |
-
obj ( Any
) –
Object deserialized from JSON.
|
Source code in src/pyobjson/data.py
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99 | def deserialize(json_data: Any, pyobjson_base_custom_subclasses_by_key: Dict[str, Type]) -> Any:
"""Recursive method to deserialize JSON into typed data structures for conversion to custom Python objects.
Args:
json_data (Any): JSON data to be deserialized.
pyobjson_base_custom_subclasses_by_key (dict[str, Type]): Dictionary with snakecase strings of all subclasses of
PythonObjectJson as keys and subclasses as values.
Returns:
obj (Any): Object deserialized from JSON.
"""
base_subclasses: Dict[str, Type] = pyobjson_base_custom_subclasses_by_key
# TODO: handle correct deserialization of specific serialized classes like set
if isinstance(json_data, list): # recursively deserialize all elements if json_data is a list
return [deserialize(item, base_subclasses) for item in json_data]
elif isinstance(json_data, dict): # recursively deserialize all values if json_data is a dictionary
# noinspection PyUnboundLocalVariable
if len(json_data) == 1 and (single_key := next(iter(json_data.keys()))) and single_key in base_subclasses:
# check if json_data is a dict with only one key that matches a custom subclass for object derivation
# noinspection PyPep8Naming
ClassObject = base_subclasses[single_key] # retrieve custom subclass
class_args = getfullargspec(ClassObject.__init__).args[1:] # get __init__ arguments for custom subclass
class_attributes: Dict[str, Any] = json_data[single_key] # get JSON to be deserialized
# create an instance of the custom subclass using the __init__ arguments
class_instance = ClassObject(
**{
k: deserialize(v, base_subclasses)
for k, v in class_attributes.items()
if k in class_args
}
)
# assign the remaining class attributes to the created class instance
vars(class_instance).update(
{k: deserialize(v, base_subclasses) for k, v in derive_typed_key_value_pairs(class_attributes).items()}
)
return class_instance
else:
return {k: deserialize(v, base_subclasses) for k, v in derive_typed_key_value_pairs(json_data).items()}
else:
return json_data
|