如何使Python类可序列化?
一个简单的课程:
class FileItem:
def __init__(self, fname):
self.fname = fname
Run Code Online (Sandbox Code Playgroud)
我该怎么做才能得到输出:
>>> import json
>>> my_file = FileItem('/foo/bar')
>>> json.dumps(my_file)
TypeError: Object of type 'FileItem' is not JSON serializable
Run Code Online (Sandbox Code Playgroud)
没有错误(__CODE__)
3.7中的标准库可以递归地将数据类转换为dict(来自docs的示例):
from dataclasses import dataclass, asdict
from typing import List
@dataclass
class Point:
x: int
y: int
@dataclass
class C:
mylist: List[Point]
p = Point(10, 20)
assert asdict(p) == {'x': 10, 'y': 20}
c = C([Point(0, 0), Point(10, 4)])
tmp = {'mylist': [{'x': 0, 'y': 0}, {'x': 10, 'y': 4}]}
assert asdict(c) == tmp
Run Code Online (Sandbox Code Playgroud)
我正在寻找一种方法,在存在嵌套时将字典转回数据类.喜欢的东西,C(**tmp)只有工作,如果数据类的字段是简单类型,而不是自己的数据类.我熟悉jsonpickle,但它带有一个突出的安全警告.
是否有任何优雅的方式使Python JSON编码器支持日期时间?一些第三方模块或简单的黑客?
我正在使用龙卷风的数据库包装器从db中获取一些原始数据以生成json.查询结果包括常规MySQL时间戳列.
Python的默认json编码器不支持自己的日期时间类型,这是非常烦人的,这在所有类型的数据库查询中都很常见.
我不想修改Python自己的json编码器.任何好的做法?非常感谢!
ps:我通过修改Python JSON编码器默认方法找到了一个脏黑客:
更改:
def default(self, o):
raise TypeError(repr(o) + " is not JSON serializable")
Run Code Online (Sandbox Code Playgroud)
至:
def default(self, o):
from datetime import date
from datetime import datetime
if isinstance(o, datetime):
return o.isoformat()
elif isinstance(o, date):
return o.isoformat()
else:
raise TypeError(repr(o) + " is not JSON serializable")
Run Code Online (Sandbox Code Playgroud)
好吧,它只是开发环境的临时解决方案.
但是对于长期解决方案或生产环境,这非常难看,每次部署到新服务器时我都必须进行修改.
有没有更好的办法?我不想修改Python代码本身,也不想修改Tornado源代码.我能用自己的项目代码做些什么来实现这一目标吗?最好是一步到位.
非常感谢!
我需要 进一步回答有关使 Python json 编码器支持 Python 的新数据类的问题:考虑它们何时处于嵌套结构json serialization of @dataclass中。
考虑:
import json
from attr import dataclass
from dataclasses_json import dataclass_json
@dataclass
@dataclass_json
class Prod:
id: int
name: str
price: float
prods = [Prod(1,'A',25.3),Prod(2,'B',79.95)]
pjson = json.dumps(prods)
Run Code Online (Sandbox Code Playgroud)
这给了我们:
TypeError: Object of type Prod is not JSON serializable
Run Code Online (Sandbox Code Playgroud)
请注意,上面确实包含了答案之一/sf/answers/4178169831/。它声称通过装饰器支持嵌套案例dataclass_json。显然这实际上行不通。
我还尝试了另一个答案/sf/answers/3590072461/:
class EnhancedJSONEncoder(json.JSONEncoder):
def default(s, o):
if dataclasses.is_dataclass(o):
return dataclasses.asdict(o)
return super().default(o)
Run Code Online (Sandbox Code Playgroud)
我为它创建了一个辅助方法:
def jdump(s,foo):
return json.dumps(foo, cls=s.c.EnhancedJSONEncoder)
Run Code Online (Sandbox Code Playgroud)
但使用该方法也不会影响(错误)结果。还有其他提示吗?