如何将深度嵌套JSON反序列化为Attr定义的Python类实例?
如何将嵌套JSON反序列化为Attrs类实例?
我来帮你搞定这个嵌套JSON转Attrs类的问题,咱们一步步来:
1. 先修正并补全你的类定义
首先注意你原来的LinkInfo类里有个小问题:link字段应该对应JSON里的rel属性,应该是笔误;另外method字段的转换器也没写完。我先把类定义补全修正:
import attr import typing as ty import enum class HttpMethod(enum.Enum): GET = 0 HEAD = 1 POST = 2 PUT = 3 DELETE = 4 CONNECT = 5 OPTIONS = 6 TRACE = 7 PATCH = 8 # 修正LinkInfo类,对应JSON结构 @attr.s(frozen=True, auto_attribs=True) class LinkInfo: href: str rel: str # 替换原来的link,对应JSON的rel字段 method: HttpMethod # 定义顶层类对应整个JSON结构 @attr.s(frozen=True, auto_attribs=True) class ApiResponse: title: str links: ty.List[LinkInfo]
2. 编写反序列化逻辑
因为JSON里的method是嵌套的{"method": "string"}结构,我们需要把它转成HttpMethod枚举。这里有两种实用方式:
方式一:手动处理嵌套结构
写一个简单的反序列化函数,手动解析每个字段,逻辑更直观:
import json def deserialize_json(json_str: str) -> ApiResponse: data = json.loads(json_str) # 逐个处理links数组中的元素 link_instances = [] for link_data in data["links"]: # 提取嵌套的method字符串,转成枚举 method_enum = HttpMethod[link_data["method"]["method"].upper()] link_instance = LinkInfo( href=link_data["href"], rel=link_data["rel"], method=method_enum ) link_instances.append(link_instance) return ApiResponse(title=data["title"], links=link_instances)
方式二:用Attrs的转换器简化代码
给method字段添加转换器,自动处理嵌套结构,这样代码更简洁优雅:
# 定义method字段的转换器函数 def convert_method(value): # 如果是嵌套字典,先取出method值;如果是字符串直接用 if isinstance(value, dict): value = value["method"] # 转成大写后匹配枚举 return HttpMethod[value.upper()] # 更新LinkInfo类,添加转换器 @attr.s(frozen=True, auto_attribs=True) class LinkInfo: href: str rel: str method: HttpMethod = attr.ib(converter=convert_method) # 简化后的反序列化函数 def deserialize_json(json_str: str) -> ApiResponse: data = json.loads(json_str) # 直接用**解包每个link数据,转换器会自动处理method links = [LinkInfo(**link_data) for link_data in data["links"]] return ApiResponse(title=data["title"], links=links)
3. 测试验证
用你提供的JSON示例来测试,看看效果:
json_data = """{ "title": "Sample API Response", "links": [ { "href": "https://example.com/users", "method": { "method": "GET" }, "rel": "users" }, { "href": "https://example.com/users", "method": { "method": "POST" }, "rel": "create-user" } ] }""" response = deserialize_json(json_data) print(response) # 输出:ApiResponse(title='Sample API Response', links=[LinkInfo(href='https://example.com/users', rel='users', method=<HttpMethod.GET: 0>), LinkInfo(href='https://example.com/users', rel='create-user', method=<HttpMethod.POST: 2>)])
这样就完美把嵌套JSON转换成Attrs类的实例了,而且因为用了frozen=True,实例是不可变的,完全符合你的定义要求。
内容的提问来源于stack exchange,提问作者Christian Sauer
相关产品推荐
相关产品推荐

