如何不修改原有__init__方法将JSON解析为Python嵌套自定义类实例
实现方案
方案1:纯标准库实现轻量递归反序列化(无需修改现有类)
该方案完全保留现有类的__init__逻辑,无需引入第三方依赖,核心逻辑是根据类的类型注解递归转换嵌套结构:
from typing import get_type_hints, List, Dict import json # 现有类无需任何修改 class C(object): def __init__(self, name: str): self.name = name class B(object): def __init__(self, name: str, c: Dict[str, C]): self.name = name self.c = c class A(object): def __init__(self, name: str, b: List[B]): self.name = name self.b = b def deserialize(data, target_type): # 获取容器类型的原始类型 origin_type = getattr(target_type, '__origin__', None) # 处理列表泛型 if origin_type is list: item_type = target_type.__args__[0] return [deserialize(item, item_type) for item in data] # 处理字典泛型 elif origin_type is dict: key_type, value_type = target_type.__args__ return {deserialize(k, key_type): deserialize(v, value_type) for k, v in data.items()} # 处理自定义类 elif hasattr(target_type, '__init__'): init_type_hints = get_type_hints(target_type.__init__) init_kwargs = {} for param_name, param_type in init_type_hints.items(): if param_name == 'return': continue init_kwargs[param_name] = deserialize(data[param_name], param_type) return target_type(**init_kwargs) # 基础类型直接返回 else: return data # 使用示例 # 序列化 test_c = C(name="test_c") test_b = B(name="test_b", c={"c1": test_c}) test_a = A(name="test_a", b=[test_b]) dump = json.dumps(test_a, default=lambda o: o.__dict__) # 反序列化 load_data = json.loads(dump) object_a = deserialize(load_data, A) # 类型校验结果 print(type(object_a)) # <class '__main__.A'> 符合预期 print(type(object_a.b)) # <class 'list'> 符合预期 print(type(object_a.b[0])) # <class '__main__.B'> 符合预期 print(type(object_a.b[0].c["c1"])) # <class '__main__.C'> 符合预期
方案2:第三方库实现(适合复杂嵌套场景)
如果嵌套结构非常复杂,可借助pydantic库简化实现,仅需给现有类加装饰器,原有__init__逻辑完全保留:
from pydantic.dataclasses import dataclass from typing import List, Dict import json @dataclass class C(object): def __init__(self, name: str): self.name = name @dataclass class B(object): def __init__(self, name: str, c: Dict[str, C]): self.name = name self.c = c @dataclass class A(object): def __init__(self, name: str, b: List[B]): self.name = name self.b = b # 反序列化直接调用即可 load_data = json.loads(dump) object_a = A(**load_data)
内容的提问来源于stack exchange,提问作者IgorZ
相关产品推荐
相关产品推荐

