如何创建可序列化的simplejson类

8 投票
2 回答
5368 浏览
提问于 2025-04-16 10:44

我有一个类是这样定义的:

class A:
    def __init__(self):
        self.item1 = None
    def __repr__(self):
        return str(self.__dict__)

当我执行:

>>> import simplejson
>>> myA = A()
>>> simplejson.dumps(myA)
TypeError: {'item1': None} is not JSON serializable

我找不到原因。

我需要在A类中添加什么特别的方法,以便simplejson能够把我的类对象转换成JSON格式吗?

2 个回答

3

根据json模块的文档(在Python 2.6中,simplejson被作为json使用),你需要扩展json.JSONEncoder这个类,重写它的默认方法,把你的对象转换成可以被序列化的类型。看起来它并不会在你的对象上寻找特定的方法。

10

你不能用 simplejson 随便把对象转成可以存储的格式。你需要在 dumpload 这两个函数里传入 defaultobject_hook。下面是个例子:

class SerializerRegistry(object):
    def __init__(self):
        self._classes = {}
    def add(self, cls):
        self._classes[cls.__module__, cls.__name__] = cls
        return cls
    def object_hook(self, dct):
        module, cls_name = dct.pop('__type__', (None, None))
        if cls_name is not None:
            return self._classes[module, cls_name].from_dict(dct)
        else:
            return dct
    def default(self, obj):
        dct = obj.to_dict()
        dct['__type__'] = [type(obj).__module__,
                           type(obj).__name__]
        return dct

registry = SerializerRegistry()

@registry.add
class A(object):
    def __init__(self, item1):
        self.item1 = item1
    def __repr__(self):
        return str(self.__dict__)
    def to_dict(self):
        return dict(item1=self.item1)
    @classmethod
    def from_dict(cls, dct):
        return cls(**dct)

s = json.dumps(A(1), default=registry.default)
a = json.loads(s, object_hook=registry.object_hook)

这样会得到:

>>> s
'{"item1": 1, "__type__": ["__main__", "A"]}'
>>> a
{'item1': 1}

但实际上,你需要一个 default 函数,它可以把你想要转存的对象变成字典,还有一个 object_hook 函数,当给它一个字典时,它能返回一个正确类型的对象(如果字典不够用的话)。最好的方法是让可转存的类里有方法,可以把对象变成字典,也可以把字典再变回对象,同时还要有一个映射,能识别这些字典属于哪个类。

你还可以给这些类加一个标识符,用作 _classes 的索引。这样的话,如果你需要移动一个类,就不会有问题了。

撰写回答