You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将深度嵌套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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:14:40