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

如何基于递归(recursion)从反序列化JSON对象(DSO)动态创建支持索引访问的Python对象(探讨描述符协议(descriptor protocol)实现方式)

解决递归序列化JSON到Python对象(支持序列索引访问)

你的现有代码已经很好地处理了字典转对象的逻辑,现在只需要扩展对序列类型(列表、元组)的递归处理,就能实现你想要的索引+属性链访问功能。

改进后的完整代码

def to_obj(item):
    '''Create object from deserialized JSON. This function calls itself recursively. 
    If item is a dict, returns an object with attributes mirroring the dict keys.
    If item is a list/tuple, returns a corresponding sequence with each element processed recursively.
    Otherwise, returns the item itself.
    :param item: <object>.
    :returns: <object>.
    '''
    if isinstance(item, dict):
        # 保持你原有的字典转自定义对象逻辑
        obj = type('__object', (object,), {})
        for key, value in item.items():
            setattr(obj, key, to_obj(value))
        return obj
    elif isinstance(item, (list, tuple)):
        # 递归处理序列中的每一个元素
        processed_items = [to_obj(element) for element in item]
        # 保持原序列的类型(列表返回列表,元组返回元组)
        if isinstance(item, tuple):
            return tuple(processed_items)
        return processed_items
    else:
        return item

测试验证

用你提供的包含序列的示例数据测试:

artifact = {
    "k1": "value1",
    "k2": {
        "k2key1": "k2value1",
        "k2key2": [
            {
                "item0key1": "item0value1",
                "item0key2": "item0value2"
            },
            {
                "item1key1": "item1value1",
                "item1key2": "item1value2"
            }
        ]
    }
}

obj = to_obj(artifact)
print(obj.k2.k2key2[1].item1key2)  # 输出: item1value2

关于描述符协议的说明

你提到Martijn Pieters提到的描述符协议,其实对于序列的索引访问场景,我们不需要用到描述符——描述符更多用于属性访问的精细化控制(比如动态计算属性、权限校验等)。在这里,我们只需要让序列中的每个元素递归转成对象,同时保留序列本身的索引能力即可,直接使用Python内置的列表/元组(或自定义容器类)实现__getitem__就足够优雅和简洁。

如果想要完全自定义序列对象(而非依赖内置列表),可以实现一个简单的容器类:

class IndexableSequence:
    def __init__(self, items):
        self._elements = [to_obj(item) for item in items]
    
    def __getitem__(self, idx):
        return self._elements[idx]
    
    def __len__(self):
        return len(self._elements)
    
    # 可选:支持迭代
    def __iter__(self):
        return iter(self._elements)

然后在to_obj的序列分支中返回IndexableSequence(item)即可,这样序列也是自定义类型,但功能上和直接用列表是一致的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 05:44:08