如何基于递归(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
相关产品推荐
相关产品推荐

