您如何在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)
有更好/更清洁的方法吗?我不需要将字典逐个重建为简单的字典。
通过将json
子类化,然后用猴子修补dict
用来创建json对象字符串的方法,可以愚弄dict
认为它正在处理实际的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
您的代码非常接近。以下解决方案将一个函数传递给JSON编码器,该编码器将AttrDict
s转换为普通字典。普通的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简化了代码。
如果您确定AttrDict对象中没有无效数据,则可以单线保存它: