我尝试从 API 接受数据,然后使用 Pydantic 基本模型验证响应结构。但是,我遇到的情况是,有时某些字段不会包含在响应中,而有时会包含在响应中。问题是,当我尝试验证结构时,Pydantic 开始抱怨这些字段“丢失”,尽管它们有时可能会丢失。我真的不明白如何将一个字段定义为“missible”。文档提到,仅定义为名称和类型的字段被认为是这种方式,但我没有任何运气
这是我想要完成的简单示例
# Response: {a: 1, b: "abc", c: ["a", "b", "c"]}
response: dict = json.loads(request_response)
# Pydantic Base Model
from pydantic import BaseModel
class Model(BaseModel):
a: int
b: str
c: List[str]
d: float
# Validating
Model(**response)
# Return: ValidationError - Missing "d" field
如何做我这样做是为了“d”不会导致验证抛出错误?我尝试将“d”切换为
d: Optional[float]
和
d: Optional[float] = 0.0
,但没有任何效果。
谢谢!
你是对的,在 Pydantic 中,只需要类型提示就可以使字段可选。但是,你遇到的问题与 Pydantic 无关,而是与你如何将
Optional[float]
解释为字段类型有关。
当你在 Pydantic 模型中声明
d: Optional[float]
时,你是在说:
-
d
是可选的: 它可能存在于你的数据中,也可能不存在。 -
如果
d
存在,它必须是一个float
: 它不能是其他类型,也不能是None
。
在你的代码中,你在没有
d
键的情况下发送一个字典给你的 Pydantic 模型,这意味着 Pydantic 无法对其进行验证,因为如果它存在,它应该是一个浮点数。
有几种方法可以解决此问题:
-
使用
typing.Union
处理潜在的缺失值:
from typing import List, Union
from pydantic import BaseModel
class Model(BaseModel):
a: int
b: str
c: List[str]
d: Union[float, None] = None
response_1 = {"a": 1, "b": "abc", "c": ["a", "b", "c"]}
response_2 = {"a": 1, "b": "abc", "c": ["a", "b", "c"], "d": 1.23}
print(Model(**response_1))
# Output: Model(a=1, b='abc', c=['a', 'b', 'c'], d=None)
print(Model(**response_2))
# Output: Model(a=1, b='abc', c=['a', 'b', 'c'], d=1.23)
在这里,我们声明
d
可以是
float
类型或
None
。如果未提供,则默认值为
None
。
-
使用
...
作为字段的类型提示:
from pydantic import BaseModel
class Model(BaseModel):
a: int
b: str
c: list[str]
d: ... = None
response_1 = {"a": 1, "b": "abc", "c": ["a", "b", "c"]}
response_2 = {"a": 1, "b": "abc", "c": ["a", "b", "c"], "d": 1.23}
print(Model(**response_1))
# Output: Model(a=1, b='abc', c=['a', 'b', 'c'], d=None)
print(Model(**response_2))
# Output: Model(a=1, b='abc', c=['a', 'b', 'c'], d=1.23)
...
作为类型提示意味着 Pydantic 将接受任何类型的
d
,包括
None
,或者根本不使用它。
这两种解决方案都将按预期工作,并允许你处理
d
字段的可选性。 选择哪种解决方案取决于你的具体需求和偏好。