如何在Python中将JSON反序列化为类并通过IntelliSense访问属性
问题描述
给定如下JSON配置:
{ "objectId": "068acfee-e5bc-4b27-ad80-59cf0adac4d9", "name": "abc", "address": { "doorNo": 23, "pinCode": "456" } }
当前通过自定义Payload类反序列化后,仅能以p.address['doorNo']的方式访问嵌套字段,希望实现类似C# Newtonsoft库的点式访问(p.address.doorNo),同时支持PyCharm的IntelliSense代码提示。环境信息:Python 3.9.10、PyCharm 2022.1社区版。
解决方案
方法1:递归转换嵌套字典为自定义对象
修改Payload类,递归处理所有嵌套字典,将其也转换为可点式访问的对象:
import json class Payload: def __init__(self, data): for key, value in data.items(): if isinstance(value, dict): setattr(self, key, Payload(value)) else: setattr(self, key, value) # 使用示例 body = json.loads('''{ "objectId": "068acfee-e5bc-4b27-ad80-59cf0adac4d9", "name": "abc", "address": { "doorNo": 23, "pinCode": "456" } }''') p = Payload(body) doorNumber = p.address.doorNo print(doorNumber) # 输出23
注意:该方法能实现点式访问,但PyCharm无法识别动态添加的属性,无法提供IntelliSense提示。
方法2:使用dataclasses定义强类型结构(推荐,支持IntelliSense)
利用Python 3.7+内置的dataclasses定义与JSON结构匹配的类,配合json模块完成反序列化,PyCharm可识别类的属性并提供完整代码提示:
import json from dataclasses import dataclass @dataclass class Address: doorNo: int pinCode: str @dataclass class Payload: objectId: str name: str address: Address # 自定义反序列化函数 def deserialize_payload(json_str: str) -> Payload: data = json.loads(json_str) # 解析嵌套的address字段 address_data = data.pop('address') data['address'] = Address(**address_data) return Payload(**data) # 使用示例 body = '''{ "objectId": "068acfee-e5bc-4b27-ad80-59cf0adac4d9", "name": "abc", "address": { "doorNo": 23, "pinCode": "456" } }''' p = deserialize_payload(body) doorNumber = p.address.doorNo print(doorNumber) # 输出23
方法3:使用pydantic库(简洁高效,支持自动校验)
若允许安装第三方库,pydantic是更优选择,它能自动处理JSON反序列化、类型校验,且完美支持IntelliSense:
首先安装库:
pip install pydantic
实现代码:
from pydantic import BaseModel class Address(BaseModel): doorNo: int pinCode: str class Payload(BaseModel): objectId: str name: str address: Address # 使用示例 body = '''{ "objectId": "068acfee-e5bc-4b27-ad80-59cf0adac4d9", "name": "abc", "address": { "doorNo": 23, "pinCode": "456" } }''' # 直接解析JSON字符串 p = Payload.parse_raw(body) # 也可解析已加载的字典:p = Payload(**json.loads(body)) doorNumber = p.address.doorNo print(doorNumber) # 输出23
pydantic会自动处理嵌套结构转换,同时提供类型校验,若JSON数据不符合定义的类型,会直接抛出异常,避免运行时错误。
内容的提问来源于stack exchange,提问作者KBNanda
相关产品推荐
相关产品推荐

