将嵌套的Python对象转换为字典的最经济方法是什么?
我有一些SQLAlchemy对象,这些对象里面又包含了更多的SQLAlchemy对象,层层嵌套,大约有五层。我想把这些对象都转换成字典形式。
我可以通过使用__dict__
这个属性把一个对象转换成字典,这没问题。但是,我在想怎么才能把所有嵌套的对象也一起转换,而不需要每一层都单独处理。
到目前为止,这是我想到的最好办法,但它没有正确地递归处理。基本上只处理了一层就停止了,所以我的逻辑显然有问题。你能看出哪里不对吗?
我希望能做到:
all_dict = myDict(obj.__dict__)
def myDict(d):
for k,v in d.items():
if isinstance(v,list):
d[k] = [myDict(i.__dict__) for i in v]
else:
d[k] = v
return d
2 个回答
47
生活小窍门:
def to_dict(obj):
return json.loads(json.dumps(obj, default=lambda o: o.__dict__))
这个方法利用了 json.dumps()
(或者 json.dump()
)里的 default
输入。它通过返回那些不能直接转换成 JSON 格式的对象的 __dict__
表示来解决问题。需要注意的是,如果对象里面有一些不标准的数据结构(比如 NumPy 或 Pandas),这个方法可能就不管用了。以下是来自 json.dump 文档 的描述:
如果指定了
default
,它应该是一个函数,用来处理那些无法被直接转换的对象。这个函数应该返回一个可以被转换成 JSON 格式的对象,或者抛出一个 TypeError。如果没有指定,程序会抛出 TypeError。
16
我不太确定我是否完全理解你想要的东西,但如果我没理解错的话,这个函数可以满足你的需求:它会在一个对象的属性中进行递归搜索,最终生成一个嵌套的字典和列表结构,最后的结果是一些没有__dict__属性的Python对象。在SQLAlchemy的情况下,这些对象很可能是基本的Python类型,比如数字和字符串。(如果这样不行,可以把“hasattr dict”这个测试换成更合适的东西,这样就能根据你的需求修复代码。)
def my_dict(obj):
if not hasattr(obj,"__dict__"):
return obj
result = {}
for key, val in obj.__dict__.items():
if key.startswith("_"):
continue
element = []
if isinstance(val, list):
for item in val:
element.append(my_dict(item))
else:
element = my_dict(val)
result[key] = element
return result