如何使一个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
如何使一个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
其他回答
为了在10年前的火灾中再添加一个日志,我还将为这个任务提供数据类向导,假设您使用的是Python 3.6+。这可以很好地用于数据类,这实际上是3.7+版本的python内置模块。
dataclass-wizard库将把对象(及其所有属性递归地)转换为dict,并使用fromdict使反向(反序列化)非常简单。另外,这里是PyPi链接:https://pypi.org/project/dataclass-wizard/。
import dataclass_wizard
import dataclasses
@dataclasses.dataclass
class A:
hello: str
a_field: int
obj = A('world', 123)
a_dict = dataclass_wizard.asdict(obj)
# {'hello': 'world', 'aField': 123}
或者如果你想要一个字符串:
a_str = jsons.dumps(dataclass_wizard.asdict(obj))
或者您的类是否从dataclass_wizard扩展。JSONWizard:
a_str = your_object.to_json()
最后,标准库还支持Union类型的数据类,这基本上意味着可以将dict反序列化为类C1或C2的对象。例如:
from dataclasses import dataclass
from dataclass_wizard import JSONWizard
@dataclass
class Outer(JSONWizard):
class _(JSONWizard.Meta):
tag_key = 'tag'
auto_assign_tags = True
my_string: str
inner: 'A | B' # alternate syntax: `inner: typing.Union['A', 'B']`
@dataclass
class A:
my_field: int
@dataclass
class B:
my_field: str
my_dict = {'myString': 'test', 'inner': {'tag': 'B', 'myField': 'test'}}
obj = Outer.from_dict(my_dict)
# True
assert repr(obj) == "Outer(my_string='test', inner=B(my_field='test'))"
obj.to_json()
# {"myString": "test", "inner": {"myField": "test", "tag": "B"}}
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))
这对我来说很有效:
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))
这是我的3美分… 这演示了一个树状python对象的显式json序列化。 注意:如果你真的想要这样的代码,你可以使用twisted FilePath类。
import json, sys, os
class File:
def __init__(self, path):
self.path = path
def isdir(self):
return os.path.isdir(self.path)
def isfile(self):
return os.path.isfile(self.path)
def children(self):
return [File(os.path.join(self.path, f))
for f in os.listdir(self.path)]
def getsize(self):
return os.path.getsize(self.path)
def getModificationTime(self):
return os.path.getmtime(self.path)
def _default(o):
d = {}
d['path'] = o.path
d['isFile'] = o.isfile()
d['isDir'] = o.isdir()
d['mtime'] = int(o.getModificationTime())
d['size'] = o.getsize() if o.isfile() else 0
if o.isdir(): d['children'] = o.children()
return d
folder = os.path.abspath('.')
json.dump(File(folder), sys.stdout, default=_default)
Json在它可以打印的对象方面受到限制,而jsonpickle(你可能需要一个PIP安装jsonpickle)在它不能缩进文本方面受到限制。如果你想检查一个你不能改变类的对象的内容,我仍然找不到比:
import json
import jsonpickle
...
print json.dumps(json.loads(jsonpickle.encode(object)), indent=2)
注意:他们仍然不能打印对象方法。