我正在尝试使用 Pydantic 验证 Rest API 的 POST 请求负载。申请人列表可以包含主要申请人和可选的其他申请人。到目前为止,我已经编写了下面列出的 Pydantic 模型,以尝试反映这一点。Rest API json 有效负载使用布尔字段isPrimary来区分主要申请人和其他申请人。
from datetime import date
from pydantic import BaseModel, validator
from typing import List, Literal, Optional, Union
class PrimaryApplicant(BaseModel):
isPrimary: Literal[True]
dateOfBirth: Optional[date]
class OtherApplicant(BaseModel):
isPrimary: Literal[False]
dateOfBirth: date
relationshipStatus: Literal["family", "friend", "other", "partner"]
class Application(BaseModel):
applicants: List[Union[PrimaryApplicant, OtherApplicant]]
@validator("applicants")
def validate(
cls,
v: List[Union[PrimaryApplicant, OtherApplicant]]
) -> List[Union[PrimaryApplicant, OtherApplicant]]:
list_count = len(v)
primary_count = len(
list(
filter(lambda item: item.isPrimary, v)
)
)
secondary_count = list_count - primary_count
if primary_count > 1:
raise ValueError("Only one primary applicant required")
if secondary_count > 1:
raise ValueError("Only one secondary applicant allowed")
return v
def main() -> None:
data_dict = {
"applicants": [
{
"isPrimary": True
},
{
"isPrimary": False,
"dateOfBirth": date(1990, 1, 15),
"relationshipStatus": "family"
},
]
}
_ = Application(**data_dict)
if __name__ == "__main__":
main()
Run Code Online (Sandbox Code Playgroud)
使用上面列出的示例 json 有效负载,当我尝试从有效负载中删除一些必需的强制字段时,会正确引发OtherApplicanta 。ValidationError例如,如果我尝试删除“relationshipStatus”或“dateOfBirth”字段,则会引发错误。然而,isPrimaryPydantic 也报告该字段无效。Pydantic 认为isPrimary字段应该是 True???下面列出了 Pydantic 验证输出示例。
OtherApplicant为什么 Pydantic 期望json 负载中的列表项的isPrimary 字段应该为 True ?PrimaryApplicant由于使用了 ,它是否以某种方式将有效负载与 关联起来Union?如果是这样,我如何让 Pydantic 使用该isPrimary字段来区分列表有效负载中的主要申请人和其他申请人?
pydantic.error_wrappers.ValidationError: 2 validation errors for Application
applicants -> 1 -> isPrimary
unexpected value; permitted: True (type=value_error.const; given=False; permitted=(True,))
applicants -> 1 -> dateOfBirth
field required (type=value_error.missing)
Run Code Online (Sandbox Code Playgroud)
pydantic.error_wrappers.ValidationError: 2 validation errors for Application
applicants -> 1 -> isPrimary
unexpected value; permitted: True (type=value_error.const; given=False; permitted=(True,))
applicants -> 1 -> relationshipStatus
field required (type=value_error.missing)
Run Code Online (Sandbox Code Playgroud)
ano*_*spp 22
通过在Pydantic GitHub 存储库上询问也找到了答案
升级到 Pydantic 1.9 并添加:
Applicant = Annotated[
Union[PrimaryApplicant, OtherApplicant],
Field(discriminator="isPrimary")]
Run Code Online (Sandbox Code Playgroud)
applicants: List[Applicant]现在我的模型中可以有字段了Application。该isPrimary字段被标记为用于区分主申请人和其他申请人。
因此,完整的代码清单是:
from datetime import date
from pydantic import BaseModel, Field, validator
from typing import List, Literal, Optional, Union
from typing_extensions import Annotated
class PrimaryApplicant(BaseModel):
isPrimary: Literal[True]
dateOfBirth: Optional[date]
class OtherApplicant(BaseModel):
isPrimary: Literal[False]
dateOfBirth: date
relationshipStatus: Literal["family", "friend", "other", "partner"]
Applicant = Annotated[
Union[PrimaryApplicant, OtherApplicant],
Field(discriminator="isPrimary")]
class Application(BaseModel):
applicants: List[Applicant]
@validator("applicants")
def validate(cls, v: List[Applicant]) -> List[Applicant]:
list_count = len(v)
primary_count = len(
list(
filter(lambda item: item.isPrimary, v)
)
)
secondary_count = list_count - primary_count
if primary_count > 1:
raise ValueError("Only one primary applicant required")
if secondary_count > 1:
raise ValueError("Only one secondary applicant allowed")
return v
def main() -> None:
data_dict = {
"applicants": [
{
"isPrimary": True
},
{
"isPrimary": False,
"relationshipStatus": "family"
},
]
}
_ = Application(**data_dict)
if __name__ == "__main__":
main()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14008 次 |
| 最近记录: |