如何使一个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

当前回答

首先,我们需要使我们的对象符合JSON,这样我们就可以使用标准JSON模块转储它。我是这样做的:

def serialize(o):
    if isinstance(o, dict):
        return {k:serialize(v) for k,v in o.items()}
    if isinstance(o, list):
        return [serialize(e) for e in o]
    if isinstance(o, bytes):
        return o.decode("utf-8")
    return o

其他回答

import json

class Foo(object):
    def __init__(self):
        self.bar = 'baz'
        self._qux = 'flub'

    def somemethod(self):
        pass

def default(instance):
    return {k: v
            for k, v in vars(instance).items()
            if not str(k).startswith('_')}

json_foo = json.dumps(Foo(), default=default)
assert '{"bar": "baz"}' == json_foo

print(json_foo)

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

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

加拉科给出了一个非常简洁的答案。我需要修复一些小的东西,但这是有效的:

Code

# Your custom class
class MyCustom(object):
    def __json__(self):
        return {
            'a': self.a,
            'b': self.b,
            '__python__': 'mymodule.submodule:MyCustom.from_json',
        }

    to_json = __json__  # supported by simplejson

    @classmethod
    def from_json(cls, json):
        obj = cls()
        obj.a = json['a']
        obj.b = json['b']
        return obj

# Dumping and loading
import simplejson

obj = MyCustom()
obj.a = 3
obj.b = 4

json = simplejson.dumps(obj, for_json=True)

# Two-step loading
obj2_dict = simplejson.loads(json)
obj2 = MyCustom.from_json(obj2_dict)

# Make sure we have the correct thing
assert isinstance(obj2, MyCustom)
assert obj2.__dict__ == obj.__dict__

注意,加载需要两个步骤。现在是__python__属性 未使用。

这种情况有多普遍?

使用AlJohri的方法,我检查了流行的方法:

序列化(Python -> JSON):

To_json: 266,595 on 2018-06-27 toJSON: 96,307 on 2018-06-27 __json__: 8504 on 2018-06-27 For_json: 6937 on 2018-06-27

反序列化(JSON -> Python):

From_json: 226,101 on 2018-06-27

一个非常简单的一行程序解决方案

import json

json.dumps(your_object, default=lambda __o: __o.__dict__)

结束!

下面是一个测试。

import json
from dataclasses import dataclass


@dataclass
class Company:
    id: int
    name: str

@dataclass
class User:
    id: int
    name: str
    email: str
    company: Company


company = Company(id=1, name="Example Ltd")
user = User(id=1, name="John Doe", email="john@doe.net", company=company)


json.dumps(user, default=lambda __o: __o.__dict__)

输出:

{
  "id": 1, 
  "name": "John Doe", 
  "email": "john@doe.net", 
  "company": {
    "id": 1, 
    "name": "Example Ltd"
  }
}

我最喜欢Lost Koder的方法。当我试图序列化成员/方法不可序列化的更复杂的对象时,我遇到了问题。这是我的实现,工作在更多的对象:

class Serializer(object):
    @staticmethod
    def serialize(obj):
        def check(o):
            for k, v in o.__dict__.items():
                try:
                    _ = json.dumps(v)
                    o.__dict__[k] = v
                except TypeError:
                    o.__dict__[k] = str(v)
            return o
        return json.dumps(check(obj).__dict__, indent=2)