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

如何将带type字段的JSON结构转换为嵌套Python dataclass对象树

嵌套带type标识的JSON转dataclass对象树实现

原代码问题分析

  • 未接收递归调用的返回值,转换后的子对象没有回填到父对象的字段中
  • 处理字典类型时,遍历第一个字段就提前返回,剩余字段完全未处理
  • 列表类型处理逻辑没有返回转换后的列表,上层无法拿到子元素的转换结果
  • 直接修改传入的json_obj会污染原始数据,建议先拷贝再操作

完整实现代码

import json
from abc import ABC
from dataclasses import dataclass
from typing import List, Dict, Type, Any

# 全局注册器
game_object_registry: Dict[str, Type["GameObject"]] = {}

# 自动注册装饰器,无需手动往注册器中添加类
def register_game_object(cls: Type["GameObject"]) -> Type["GameObject"]:
    game_object_registry[cls.__name__] = cls
    return cls

# 业务类定义
@register_game_object
@dataclass
class GameObject(ABC):
    pass

@register_game_object
@dataclass
class Character(GameObject):
    name: str

@register_game_object
@dataclass
class Wave(GameObject):
    enemies: List[Character]

@register_game_object
@dataclass
class Wizard(Character):
    pass

@register_game_object
@dataclass
class Archer(Character):
    pass

@register_game_object
@dataclass
class Map(GameObject):
    name: str

@register_game_object
@dataclass
class SquareRoom(Map):
    width: int
    height: int

@register_game_object
@dataclass
class Level(GameObject):
    waves: List[Wave]
    map: Map

@register_game_object
@dataclass
class Game(GameObject):
    levels: List[Level]

# 修正后的递归转换函数
def json_to_game_object(json_obj: Any, registry: Dict[str, Type[GameObject]]) -> Any:
    # 处理字典类型:先递归转换所有字段值,再生成对应类实例
    if isinstance(json_obj, dict):
        # 拷贝数据避免修改原始输入对象
        obj_dict = json_obj.copy()
        obj_type_name = obj_dict.pop("type")
        obj_cls = registry[obj_type_name]
        # 遍历所有字段完成递归转换
        for k, v in obj_dict.items():
            obj_dict[k] = json_to_game_object(v, registry)
        # 所有字段处理完成后生成实例返回
        return obj_cls(**obj_dict)
    # 处理列表类型:递归转换每个元素,返回新的转换后列表
    elif isinstance(json_obj, list):
        return [json_to_game_object(item, registry) for item in json_obj]
    # 基础类型直接返回
    else:
        return json_obj

# 测试逻辑
if __name__ == "__main__":
    json_data_str = """
    {
        "type" : "Game",
        "levels" : [
            {
                "type": "Level",
                "map" : {
                    "type" : "SquareRoom",
                    "name" : "Level 1",
                    "width" : 100,
                    "height" : 100
                },
                "waves" : [
                    {
                        "type" : "Wave",
                        "enemies" : [
                            {
                                "type" : "Wizard",
                                "name" : "Gandalf"
                            },
                            {
                                "type" : "Archer",
                                "name" : "Legolass"
                            }
                        ]
                    }
                ]
            }
        ]
    }
    """
    json_data = json.loads(json_data_str)
    game = json_to_game_object(json_data, game_object_registry)
    print(game)
    # 输出与预期完全一致:
    # Game(levels=[Level(waves=[Wave(enemies=[Wizard(name='Gandalf'), Archer(name='Legolass')])], map=SquareRoom(name='Level 1', width=100, height=100))])

内容的提问来源于stack exchange,提问作者Blue7

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 21:15:01