在 JSON 中创建自 pydantic.BaseModel exclude 如果未设置则可选
In JSON created from a pydantic.BaseModel exclude Optional if not set
我想排除所有在创建时未设置的可选值 JSON。在这个例子中:
from pydantic import BaseModel
from typing import Optional
class Foo(BaseModel):
x: int
y: int = 42
z: Optional[int]
print(Foo(x=3).json())
我得到 {"x": 3, "y": 42, "z": null}
。但我想排除 z
。不是因为它的值是 None
,而是因为它是可选的并且 z
没有关键字参数。在下面的两种情况下,我希望在 JSON.
中包含 z
Foo(x=1, z=None)
Foo(x=1, z=77)
在这个意义上如果有其他解决方案可以将z
设置为可选,我很想看看。
您可以仅排除通过 已设置 和 未设置 None 的模型字段并集而未设置的可选模型字段=36=].
Pydantic 为导出方法 model.dict(...) 提供以下参数:
exclude_unset
: whether fields which were not explicitly set when creating the model should be excluded from the returned dictionary; default False
.
exclude_none
: whether fields which are equal to None
should be excluded from the returned dictionary; default False
要合并两个字典,我们可以使用表达式 a = {**b, **c}
(来自 c
的值会覆盖来自 b
的值)。请注意,由于 Python 3.9 可以像 a = b | c
.
那样完成
from pydantic import BaseModel
from typing import Optional
from pydantic.json import pydantic_encoder
import json
class Foo(BaseModel):
x: int
y: int = 42
z: Optional[int]
def exclude_optional_dict(model: BaseModel):
return {**model.dict(exclude_unset=True), **model.dict(exclude_none=True)}
def exclude_optional_json(model: BaseModel):
return json.dumps(exclude_optional_dict(model), default=pydantic_encoder)
print(exclude_optional_json(Foo(x=3))) # {"x": 3, "y": 42}
print(exclude_optional_json(Foo(x=3, z=None))) # {"x": 3, "z": null, "y": 42}
print(exclude_optional_json(Foo(x=3, z=77))) # {"x": 3, "z": 77, "y": 42}
更新
为了使该方法适用于嵌套模型,我们需要对两个字典进行深度联合(或合并),如下所示:
def union(source, destination):
for key, value in source.items():
if isinstance(value, dict):
node = destination.setdefault(key, {})
union(value, node)
else:
destination[key] = value
return destination
def exclude_optional_dict(model: BaseModel):
return union(model.dict(exclude_unset=True), model.dict(exclude_none=True))
class Foo(BaseModel):
x: int
y: int = 42
z: Optional[int]
class Bar(BaseModel):
a: int
b: int = 52
c: Optional[int]
d: Foo
print(exclude_optional_json(Bar(a=4, d=Foo(x=3))))
print(exclude_optional_json(Bar(a=4, c=None, d=Foo(x=3, z=None))))
print(exclude_optional_json(Bar(a=4, c=78, d=Foo(x=3, z=77))))
{"a": 4, "b": 52, "d": {"x": 3, "y": 42}}
{"a": 4, "b": 52, "d": {"x": 3, "y": 42, "z": null}, "c": null}
{"a": 4, "b": 52, "c": 78, "d": {"x": 3, "y": 42, "z": 77}}
我想排除所有在创建时未设置的可选值 JSON。在这个例子中:
from pydantic import BaseModel
from typing import Optional
class Foo(BaseModel):
x: int
y: int = 42
z: Optional[int]
print(Foo(x=3).json())
我得到 {"x": 3, "y": 42, "z": null}
。但我想排除 z
。不是因为它的值是 None
,而是因为它是可选的并且 z
没有关键字参数。在下面的两种情况下,我希望在 JSON.
z
Foo(x=1, z=None)
Foo(x=1, z=77)
在这个意义上如果有其他解决方案可以将z
设置为可选,我很想看看。
您可以仅排除通过 已设置 和 未设置 None 的模型字段并集而未设置的可选模型字段=36=].
Pydantic 为导出方法 model.dict(...) 提供以下参数:
exclude_unset
: whether fields which were not explicitly set when creating the model should be excluded from the returned dictionary; defaultFalse
.
exclude_none
: whether fields which are equal toNone
should be excluded from the returned dictionary; defaultFalse
要合并两个字典,我们可以使用表达式 a = {**b, **c}
(来自 c
的值会覆盖来自 b
的值)。请注意,由于 Python 3.9 可以像 a = b | c
.
from pydantic import BaseModel
from typing import Optional
from pydantic.json import pydantic_encoder
import json
class Foo(BaseModel):
x: int
y: int = 42
z: Optional[int]
def exclude_optional_dict(model: BaseModel):
return {**model.dict(exclude_unset=True), **model.dict(exclude_none=True)}
def exclude_optional_json(model: BaseModel):
return json.dumps(exclude_optional_dict(model), default=pydantic_encoder)
print(exclude_optional_json(Foo(x=3))) # {"x": 3, "y": 42}
print(exclude_optional_json(Foo(x=3, z=None))) # {"x": 3, "z": null, "y": 42}
print(exclude_optional_json(Foo(x=3, z=77))) # {"x": 3, "z": 77, "y": 42}
更新
为了使该方法适用于嵌套模型,我们需要对两个字典进行深度联合(或合并),如下所示:
def union(source, destination):
for key, value in source.items():
if isinstance(value, dict):
node = destination.setdefault(key, {})
union(value, node)
else:
destination[key] = value
return destination
def exclude_optional_dict(model: BaseModel):
return union(model.dict(exclude_unset=True), model.dict(exclude_none=True))
class Foo(BaseModel):
x: int
y: int = 42
z: Optional[int]
class Bar(BaseModel):
a: int
b: int = 52
c: Optional[int]
d: Foo
print(exclude_optional_json(Bar(a=4, d=Foo(x=3))))
print(exclude_optional_json(Bar(a=4, c=None, d=Foo(x=3, z=None))))
print(exclude_optional_json(Bar(a=4, c=78, d=Foo(x=3, z=77))))
{"a": 4, "b": 52, "d": {"x": 3, "y": 42}}
{"a": 4, "b": 52, "d": {"x": 3, "y": 42, "z": null}, "c": null}
{"a": 4, "b": 52, "c": 78, "d": {"x": 3, "y": 42, "z": 77}}