如何使一个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
当前回答
除了Onur的答案,你可能想要处理如下的datetime类型。(以便处理:'datetime. time.)Datetime对象没有属性dict异常。)
def datetime_option(value):
if isinstance(value, datetime.date):
return value.timestamp()
else:
return value.__dict__
用法:
def toJSON(self):
return json.dumps(self, default=datetime_option, sort_keys=True, indent=4)
其他回答
Jsonweb似乎是我的最佳解决方案。参见http://www.jsonweb.info/en/latest/
from jsonweb.encode import to_object, dumper
@to_object()
class DataModel(object):
def __init__(self, id, value):
self.id = id
self.value = value
>>> data = DataModel(5, "foo")
>>> dumper(data)
'{"__type__": "DataModel", "id": 5, "value": "foo"}'
对于更复杂的类,您可以考虑使用jsonpickle工具:
jsonpickle is a Python library for serialization and deserialization of complex Python objects to and from JSON. The standard Python libraries for encoding Python into JSON, such as the stdlib’s json, simplejson, and demjson, can only handle Python primitives that have a direct JSON equivalent (e.g. dicts, lists, strings, ints, etc.). jsonpickle builds on top of these libraries and allows more complex data structures to be serialized to JSON. jsonpickle is highly configurable and extendable–allowing the user to choose the JSON backend and add additional backends.
(链接到PyPi上的jsonpickle)
Json在它可以打印的对象方面受到限制,而jsonpickle(你可能需要一个PIP安装jsonpickle)在它不能缩进文本方面受到限制。如果你想检查一个你不能改变类的对象的内容,我仍然找不到比:
import json
import jsonpickle
...
print json.dumps(json.loads(jsonpickle.encode(object)), indent=2)
注意:他们仍然不能打印对象方法。
只需要像这样添加to_json方法到你的类中:
def to_json(self):
return self.message # or how you want it to be serialized
然后将这段代码(来自这个答案)添加到所有内容的顶部:
from json import JSONEncoder
def _default(self, obj):
return getattr(obj.__class__, "to_json", _default.default)(obj)
_default.default = JSONEncoder().default
JSONEncoder.default = _default
这将会在导入json模块时monkey-patch,所以 JSONEncoder.default()自动检查特殊的to_json() 方法,并使用它对找到的对象进行编码。
就像Onur说的,但是这次你不需要更新项目中的每个json.dumps()。
为了在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"}}