使Python json编码器支持Python';新的数据类
从Python 3.7开始,有一种称为dataclass的东西:使Python json编码器支持Python';新的数据类,python,python-dataclasses,Python,Python Dataclasses,从Python 3.7开始,有一种称为dataclass的东西: from dataclasses import dataclass @dataclass class Foo: x: str 但是,以下操作失败: >>> import json >>> foo = Foo(x="bar") >>> json.dumps(foo) TypeError: Object of type Foo is not JSON serializa
from dataclasses import dataclass
@dataclass
class Foo:
x: str
但是,以下操作失败:
>>> import json
>>> foo = Foo(x="bar")
>>> json.dumps(foo)
TypeError: Object of type Foo is not JSON serializable
如何使
json.dumps()
将Foo
的实例编码为json?就像您可以为json编码器添加对或小数的支持一样,您还可以提供自定义编码器子类来序列化数据类:
import dataclasses, json
class EnhancedJSONEncoder(json.JSONEncoder):
def default(self, o):
if dataclasses.is_dataclass(o):
return dataclasses.asdict(o)
return super().default(o)
json.dumps(foo, cls=EnhancedJSONEncoder)
您不能只使用
dataclasses.asdict()
函数来转换数据类吗
口述?比如:
>>> @dataclass
... class Foo:
... a: int
... b: int
...
>>> x = Foo(1,2)
>>> json.dumps(dataclasses.asdict(x))
'{"a": 1, "b": 2}'
如果您同意使用库进行此操作,则可以使用。以下是一个例子:
从数据类导入数据类
从dataclass_json导入dataclass_json
@dataclass_json
@数据类
Foo类:
x:str
foo=foo(x=“一些字符串”)
foo_json=foo.to_json()
它还支持嵌入式数据类——如果您的数据类有一个作为另一个数据类键入的字段——如果所有已解决的数据类都有@dataclass\u json
装饰器 获取JSONified dataclass实例的方法
实现该目标有两种选择,每种选择都意味着分析哪种方法最适合您的需要:
将其提取回dataclass实例并不简单,所以您可能希望访问该答案
作为对marshmallow\u dataclass
的奖励,您可以对字段本身使用验证,当有人使用该模式从json反序列化对象时,将使用该验证
此外,请注意,marshmallow数据类为您进行了类型转换,而dataclassses json(版本:0.5.1)忽略了这一点
遵循公认的2K答案并重用自定义json编码器。使用字典解包可以找到更简单的答案
>>从数据类导入数据类
>>>@dataclass
... 类别MyData:
... prop1:int
... prop2:str
... prop3:int
...
>>>d={'prop1':5'prop2':'hi','prop3':100}
>>>我的数据=我的数据(**d)
>>>我的数据
MyData(prop1=5,prop2='hi',prop3=100)
我建议使用to_json()
方法为数据类创建父类:
导入json
从数据类导入数据类,asdict
@数据类
类别数据类别:
def to_json(self)->str:
返回json.dumps(asdict(self))
@数据类
类YourDataclass(数据类):
a:整数
b:int
x=YourDataclass(a=1,b=2)
x、 to_json()#“{”a:1,“b:2}”
如果要向所有数据类添加其他功能,这一点尤其有用。数据类可能是大型结构的深层嵌套部分。通过使用自定义编码器,您可以执行
json.dumps({“obj”:[某些东西可能包含或不包含数据类])
asasdict()将正确处理所有嵌套的数据类,因此,我们得到通常加载到jison字符串中的嵌套字典(但是!例如,在加载到字符串中之前,必须另外处理datetime类型)需要注意的是,对于名为Foo
的数据类和一个实例Foo\u instance=Foo(…)
这两个dataclasses.is\u dataclass(Foo)
和dataclasses.is\u dataclass(Foo\u instance)
计算为True
会导致dataclasses.asdict(o)的TypeError
ifo
ist是数据类本身,而不是它的一个实例。嵌套如何-例如序列化d={'a':Foo(1,2),'b':Foo(3,4)}
如何处理ndarray类型的对象?我用嵌入式数据类尝试了这个方法,但它不起作用谢谢marshmallow_数据类
这确实是一个很好的方法,可以通过验证(甚至YAML)从JSON获取真正的对象。@mickours欢迎:)顺便说一句,我没有提到它也可以在python36上工作(在引擎盖下有dataclass backport)这不支持嵌套的dataclass。如果d来自json对象,这可能会引入错误。我们通常认为在有效负载中添加字段不是一个突破性的更改,但在这里,如果您向d添加字段,它将以“获得意外的关键字参数‘prop4’”而中断
import dataclasses
import json
@dataclass.dataclass
class Foo:
x: str
foo = Foo(x='1')
json_foo = json.dumps(dataclasses.asdict(foo)) # '{"x": "1"}'
from dataclasses import field
from marshmallow_dataclass import dataclass
@dataclass
class Foo:
x: int = field(metadata={"required": True})
foo = Foo(x='1') # Foo(x='1')
json_foo = foo.Schema().dumps(foo) # '{"x": "1"}'
# Back to class instance.
Foo.Schema().loads(json_foo) # Foo(x=1)
from dataclasses import dataclass
from dataclasses_json import dataclass_json
@dataclass_json
@dataclass
class Foo:
x: int
foo = Foo(x='1')
json_foo = foo.to_json() # Foo(x='1')
# Back to class instance
Foo.from_json(json_foo) # Foo(x='1')