如何使python的json模块编码attrdict.AttrDict对象?

3 投票
3 回答
3278 浏览
提问于 2025-04-18 15:51

如何将AttrDict对象编码成json格式?

import sys, json, attrdict

ad = attrdict.AttrDict({'else': 1, 'inner': attrdict.AttrDict({'something': 2})})

json.dump(ad, sys.stdout)

这样做会失败,出现错误 TypeError: a{'something': 2} is not JSON serializable

使用一个自定义的编码器可以解决这个问题,但我必须引用私有的_mapping属性:

import sys, json, attrdict

class attrDictEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, attrdict.AttrDict):
            return obj._mapping
        return json.JSONEncoder.default(self, obj)

ad = attrdict.AttrDict({'else': 1, 'inner': attrdict.AttrDict({'something': 2})})

json.dump(ad, sys.stdout, cls=attrDictEncoder)

有没有更好、更简单的方法?我不想一个一个地把字典重建成普通字典。

3 个回答

0

如果你确定你的AttrDict对象里没有任何无效数据,你可以用一行代码把它保存起来:

json.dumps(obj, default=dict)
2

你的代码已经很接近正确了。下面的解决方案是把一个函数传给JSON编码器,这个函数可以把AttrDict类型的对象转换成普通的字典。当JSON处理程序遇到像AttrDict这样的非标准类型时,就会调用这个函数。

源代码

import json, attrdict

def as_attrdict(val):
    if not isinstance(val, attrdict.AttrDict):
        raise TypeError('not AttrDict')
    return dict(val)

ad = attrdict.AttrDict({'else': 1,
                        'inner': attrdict.AttrDict({'something': 2})})

print json.dumps(ad, default=as_attrdict)

输出结果

{"inner": {"something": 2}, "else": 1}

AttrDict是一种类似字典的对象,它允许通过键和属性两种方式来访问其中的元素。

感谢用户2357112对代码的简化。

1

我们可以通过创建一个新的类来欺骗 json,让它以为自己在处理一个真正的 dict。具体做法是先继承 dict,然后修改 json 用来生成 json 对象字符串的方法。这样,我们就能给 json 提供一个虚假的类,这个类只会调用给定的 AttrDict 的相关方法。

def as_attrdict(val):
    if not isinstance(val, AttrDict):
        raise TypeError('not AttrDict')
    return AttrDictForJson(val)


class AttrDictForJson(dict):

    def __init__(self, attrdict):
        super().__init__()
        self.items = attrdict.items
        self._len = attrdict.__len__
        # key creation necessary for json.dump to work with CPython 
        # This is because optimised json bypasses __len__ on CPython
        if self._len() != 0:
            self[None] = None

    def __len__(self):
        return self._len()

使用方法:

json_string = dumps(attrdict, default=as_attrdict)

我在 Python 3.4 上测试过这个,如果你用的是不同版本的 Python,可能需要稍微调整一下,比如把 attrdict.items 改成 attrdict.iteritems

撰写回答