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

问题描述 投票:3回答:3

您如何在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)

有更好/更清洁的方法吗?我不需要将字典逐个重建为简单的字典。

python json
3个回答
1
投票

通过将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


2
投票

您的代码非常接近。以下解决方案将一个函数传递给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简化了代码。


0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.