pydantic 转换为 jsonable dict(不是完整的 json 字符串)

mik*_*ike 4 python jsonserializer python-3.x pydantic

我想pydantic用于在 api 和数据存储之间处理数据(双向),因为它很好地支持我关心的几种类型,这些类型不是原生的 json-serializable。它比当前方法具有更好的读取/验证支持,但我还需要创建 json-serializabledict对象来写出。

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()
Run Code Online (Sandbox Code Playgroud)

印刷

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

我喜欢以下内容:

{"the_id": "4108356a-556e-484b-9447-07b56a664763"} # eg "json-compatible" dict
Run Code Online (Sandbox Code Playgroud)

看来,虽然pydantic拥有所有的映射,但是我找不到序列化的任何使用标准之外json〜递归编码器(json.dumps( ... default=pydantic_encoder))的pydantic/main.py。但我更愿意保留一个库来验证 raw->obj(pydantic 在这方面很棒)以及 obj->raw(dict),这样我就不必管理多个序列化映射。我想我可以实现类似于json使用编码器的东西,但这应该是一个常见的用例吗?

其他方法,例如dataclasses(builtin)+ 库,例如dataclasses_jsonschema向 提供此 ~ 序列化json-ready dict,但同样希望使用 pydantic 进行更强大的输入验证,同时保持对称。

mik*_*ike 15

看来这个功能已经被提出,并且(可能)受到 pydantic 的作者 samuel colvin 的青睐,如https://github.com/samuelcolvin/pydantic/issues/951#issuecomment-552463606

建议添加一个simplify参数来Model.dict()输出 jsonalbe 数据。

This code runs in a production api layer, and is exersized such that we can't use the one-line workaround suggested (just doing a full serialize (.json()) + full deserialize). We implemented a custom function to do this, descending the result of .dict() and converting types to jsonable - hopefully the above proposed functionality is added to pydantic in the future.

  • 具体添加了什么?不幸的是,到目前为止,还没有添加像“json_encoders”这样添加“dict_encoders”的功能。 (7认同)

aig*_*fer 13

另一种选择是使用以下jsonable_encoder方法(fastapi如果您已经使用该方法): https: //fastapi.tiangolo.com/tutorial/encoder/

该代码看起来非常独立,因此如果许可证允许,您可以复制粘贴它。


Sel*_*cuk 10

Pydantic 2中的官方方法是使用.model_dump()带有mode="json"参数的方法:

print(instance.model_dump(mode="json"))
Run Code Online (Sandbox Code Playgroud)

来自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
   """
Run Code Online (Sandbox Code Playgroud)


ale*_*ame 8

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

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

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

或者更有效地通过orjson

orjson.loads(Model().json())
Run Code Online (Sandbox Code Playgroud)

  • 我很欣赏您的回答,但是对于生产环境来说,不能考虑为序列化/反序列化的完整往返付费。目前我们已经实施了自定义解决方法。 (11认同)