如何使一个Python类序列化?

class FileItem:
    def __init__(self, fname):
        self.fname = fname

尝试序列化为JSON:

>>> import json
>>> x = FileItem('/foo/bar')
>>> json.dumps(x)
TypeError: Object of type 'FileItem' is not JSON serializable

当前回答

如果你能够安装一个软件包,我建议你试试dill,它在我的项目中工作得很好。这个包的一个优点是它具有与pickle相同的接口,因此如果您已经在项目中使用了pickle,则可以简单地替换为dill并查看脚本是否运行,而无需更改任何代码。所以这是一个非常便宜的解决方案!

(完全反披露:我与莳萝项目没有任何关联,也从未参与过。)

安装包:

pip install dill

然后编辑你的代码导入莳萝而不是pickle:

# import pickle
import dill as pickle

运行脚本,看看它是否有效。(如果是的话,你可能想要清理你的代码,这样你就不再隐藏pickle模块的名字了!)

关于dill可以和不能序列化的数据类型的一些细节,来自项目页面:

dill can pickle the following standard types: none, type, bool, int, long, float, complex, str, unicode, tuple, list, dict, file, buffer, builtin, both old and new style classes, instances of old and new style classes, set, frozenset, array, functions, exceptions dill can also pickle more ‘exotic’ standard types: functions with yields, nested functions, lambdas, cell, method, unboundmethod, module, code, methodwrapper, dictproxy, methoddescriptor, getsetdescriptor, memberdescriptor, wrapperdescriptor, xrange, slice, notimplemented, ellipsis, quit dill cannot yet pickle these standard types: frame, generator, traceback

其他回答

这是一个小库,它将一个对象及其所有子对象序列化为JSON,并将其解析回来:

https://github.com/tobiasholler/PyJSONSerialization/

这对我来说很有效:

class JsonSerializable(object):

    def serialize(self):
        return json.dumps(self.__dict__)

    def __repr__(self):
        return self.serialize()

    @staticmethod
    def dumper(obj):
        if "serialize" in dir(obj):
            return obj.serialize()

        return obj.__dict__

然后

class FileItem(JsonSerializable):
    ...

and

log.debug(json.dumps(<my object>, default=JsonSerializable.dumper, indent=2))

我喜欢Onur的答案,但会扩展到包括一个可选的toJSON()方法,用于对象序列化自己:

def dumper(obj):
    try:
        return obj.toJSON()
    except:
        return obj.__dict__
print json.dumps(some_big_object, default=dumper, indent=2)
import simplejson

class User(object):
    def __init__(self, name, mail):
        self.name = name
        self.mail = mail

    def _asdict(self):
        return self.__dict__

print(simplejson.dumps(User('alice', 'alice@mail.com')))

如果使用标准json,则需要定义一个默认函数

import json
def default(o):
    return o._asdict()

print(json.dumps(User('alice', 'alice@mail.com'), default=default))

我有了自己的解决办法。使用此方法,将任何文档(字典、列表、ObjectId等)传递给序列化。

def getSerializable(doc):
    # check if it's a list
    if isinstance(doc, list):
        for i, val in enumerate(doc):
            doc[i] = getSerializable(doc[i])
        return doc

    # check if it's a dict
    if isinstance(doc, dict):
        for key in doc.keys():
            doc[key] = getSerializable(doc[key])
        return doc

    # Process ObjectId
    if isinstance(doc, ObjectId):
        doc = str(doc)
        return doc

    # Use any other custom serializting stuff here...

    # For the rest of stuff
    return doc