python-3.x pydantic转换为jsonable dict(不是完整的json字符串)

um6iljoc  于 2023-03-20  发布在  Python
关注(0)|答案(4)|浏览(217)

我想使用pydantic来处理API和datastore之间的数据(双向),因为它很好地支持了我所关心的几种类型,而这些类型本身不是json可序列化的,它比当前的方法有更好的读取/验证支持,但是我还需要创建json可序列化的dict对象来写出。

from uuid import UUID, uuid4
from pydantic import BaseModel

class Model(BaseModel):
    the_id: UUID

instance = Model(the_id=uuid4())
print("1: %s" % instance.dict()
print("2: %s" % instance.json()

印刷品

{'the_id': UUID('4108356a-556e-484b-9447-07b56a664763')}
>>> inst.json()
'{"the_id": "4108356a-556e-484b-9447-07b56a664763"}'

我想要以下内容:

{"the_id": "4108356a-556e-484b-9447-07b56a664763"} # eg "json-compatible" dict

看起来尽管Pydantic拥有所有的Map,但是我找不到标准json ~递归编码器之外的任何序列化用法(json.dumps( ... default=pydantic_encoder))在pydantic/main.py中。但是我更喜欢保留一个库用于验证raw-〉obj(pydantic在这方面很棒)以及obj-〉raw(dict),这样我就不必管理多个序列化Map。我想我可以实现类似于编码器的json用法的东西,但这应该是一个常见的用例
其他方法,如dataclasses(builtin)+库(如dataclasses_jsonschema)提供了对json-ready dict的~序列化,但同样,希望使用pydantic进行更健壮的输入验证,同时保持对称。

wwodge7n

wwodge7n1#

当前版本的pydantic不支持直接创建jsonable dict,但可以使用以下技巧:

class Model(BaseModel):
    the_id: UUID = Field(default_factory=uuid4)

print(json.loads(Model().json()))
{'the_id': '4c94e7bc-78fe-48ea-8c3b-83c180437774'}

或通过orjson实现更高效率

orjson.loads(Model().json())
fae0ux8s

fae0ux8s2#

这个功能似乎已经被提出,并且(可能)受到pydantic的作者samuel colvin的青睐,如https://github.com/samuelcolvin/pydantic/issues/951#issuecomment-552463606
其提出将X1 M0 N1 X参数添加到X1 M1 N1 X以输出声纳数据。
这段代码运行在一个生产API层,并且被扩展到我们不能使用建议的一行解决方案(只做一个完整的序列化(.json())+完整的反序列化),我们实现了一个自定义函数来做这件事,将.dict()的结果降序,并将类型转换为jsonable -希望上述建议的功能在未来被添加到pydantic中。

vyswwuz2

vyswwuz23#

另一种方法是使用fastapi中的jsonable_encoder方法(如果您已经在使用该方法):https://fastapi.tiangolo.com/tutorial/encoder/
代码看起来非常独立,所以如果许可证允许,您可以复制粘贴它。

2jcobegt

2jcobegt4#

Pydantic 2中的官方方法(截至本答案尚未发布)使用的是带有mode="json"参数的.model_dump()方法:

print(instance.model_dump(mode="json"))

来自Pydantic 2 Plan文档:

def model_dump_json(self, ...) -> str:
   """
   previously `json()`, arguments as above
   effectively equivalent to `json.dump(self.model_dump(..., mode='json'))`,
   but more performant
   """

相关问题