Python中与Go Struct、json.Unmarshal等价的实现方案是什么?
Python实现类Go结构体的JSON反序列化方案
你要的按层级自定义实例类型、支持点属性访问的需求,有两种可落地的实现方式:
方案1:使用Pydantic(推荐,生产环境常用)
Pydantic 原生支持嵌套模型定义、JSON反序列化、点属性访问,完全匹配Go结构体的反序列化效果。
from pydantic import BaseModel import json # 对应Go的type body struct定义 class Body(BaseModel): Day: int Month: int Year: int # 对应Go的type dat struct定义 class Dat(BaseModel): ResponseTime: int Body: Body # 待解析的JSON字符串 e = ''' { "ResponseTime": 123, "Body": { "Day": 15, "Month": 8, "Year": 2024 } } ''' # 等价于Go的json.Unmarshal(e, &h) h = Dat.model_validate_json(e) # 点属性访问测试 print(h.ResponseTime) # 输出123 print(h.Body.Year) # 输出2024 # 嵌套层级的实例类型完全自定义 print(type(h.Body)) # 输出<class '__main__.Body'>
方案2:原生Python实现(无第三方依赖)
如果不想引入外部库,可以基于dataclass手动实现递归反序列化逻辑,解决普通object_hook无法识别层级类型的问题。
from dataclasses import dataclass import json from typing import get_type_hints # 定义分层结构体 @dataclass class Body: Day: int Month: int Year: int @dataclass class Dat: ResponseTime: int Body: Body # 自定义递归反序列化函数 def deserialize(data: dict, target_type): type_hints = get_type_hints(target_type) init_kwargs = {} for field, field_type in type_hints.items(): val = data.get(field) # 嵌套字典递归转对应自定义类型 if isinstance(val, dict) and hasattr(field_type, "__dataclass_fields__"): init_kwargs[field] = deserialize(val, field_type) else: init_kwargs[field] = val return target_type(**init_kwargs) # 使用示例 e = ''' { "ResponseTime": 123, "Body": { "Day": 15, "Month": 8, "Year": 2024 } } ''' data_dict = json.loads(e) h = deserialize(data_dict, Dat) print(h.Body.Month) # 输出8 print(type(h.Body)) # 输出<class '__main__.Body'>
原object_hook不生效的原因
object_hook是全局回调,解析JSON中所有字典时都会调用,无法感知当前字典所属的层级和对应的自定义类型,因此只能将所有字典转为同一个类的实例。
内容的提问来源于stack exchange,提问作者Arib Ansari
相关产品推荐
相关产品推荐

