将嵌套的Python对象转换为字典的最经济方法是什么?

15 投票
2 回答
15857 浏览
提问于 2025-04-17 05:24

我有一些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

撰写回答