你如何启用python的json包来编码attrdict.AttrDict对象?

时间:2014-08-03 21:10:14

标签: python json

如何在json中编码AttrDict对象?

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)

有更好/更清洁的方式吗?我不想将逐项重新构建的dicts重新构建成一个简单的dicts。

3 个答案:

答案 0 :(得分: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是一个类似字典的对象,允许以元素和属性的形式访问其元素。

感谢user2357112简化代码。

答案 1 :(得分: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

答案 2 :(得分:0)

如果您确定AttrDict对象中没有无效数据,则可以单线保存:

json.dumps(obj, default=dict)
相关问题