如何使python的json模块编码attrdict.AttrDict对象?
如何将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
。