如何为含特殊字符键的嵌套字典定义适配FastAPI的Pydantic类
解决方案
你可以通过Pydantic的Field别名功能和严格类型标注实现完整校验,分两种常见场景处理:
场景1:simpleStringName2下的特殊分隔键是固定已知的
如果请求中带|的键名是固定枚举值,用alias参数映射特殊键名和合法Python变量名即可:
from datetime import datetime from pydantic import BaseModel, Field # 定义simpleStringName2对应的嵌套结构 class SimpleStringName2Model(BaseModel): # 用alias映射实际请求中带|的键名 complicated_name1: int = Field(alias="Complicated|String|Name|with|Pipe|Characters") complicated_name2: int = Field(alias="Complicated|String|Name2|with|Pipe|Characters") # 开启严格模式,禁止传入未定义的额外字段 model_config = {"extra": "forbid"} # 定义inputs层级结构 class InputsModel(BaseModel): simpleStringName: datetime simpleStringName2: SimpleStringName2Model model_config = {"extra": "forbid"} # 顶层请求模型 class XYZ(BaseModel): inputs: InputsModel model_config = {"extra": "forbid"}
如果使用Pydantic V1,将
model_config替换为内部类Config即可:class SimpleStringName2Model(BaseModel): complicated_name1: int = Field(alias="Complicated|String|Name|with|Pipe|Characters") class Config: extra = "forbid"
场景2:simpleStringName2下的键是动态不固定的
如果该层级的键不固定,但统一满足「字符串为键、整数为值」的规则,直接用带类型参数的dict标注即可,还可以额外添加键名的正则校验:
from datetime import datetime from typing_extensions import Annotated from pydantic import BaseModel, Pattern # 可选:定义键名的规则,示例要求键必须至少包含一个| PipeKey = Annotated[str, Pattern(r".*\|.*")] class InputsModel(BaseModel): simpleStringName: datetime # 所有键为符合规则的字符串,值为整数 simpleStringName2: dict[PipeKey, int] model_config = {"extra": "forbid"} class XYZ(BaseModel): inputs: InputsModel model_config = {"extra": "forbid"}
FastAPI中使用
直接将XYZ作为路径操作函数的请求参数类型即可,FastAPI会自动完成格式校验,不符合规则的请求会直接返回422错误:
from fastapi import FastAPI app = FastAPI() @app.post("/your-api-path") def your_api(data: XYZ): # 可直接通过Python变量名访问字段 print(data.inputs.simpleStringName) # 带别名的字段也可以直接访问定义的变量名 # 固定键场景:print(data.inputs.simpleStringName2.complicated_name1) # 动态键场景:print(data.inputs.simpleStringName2.get("Complicated|String|Name|with|Pipe|Characters")) return {"status": "success"}
内容的提问来源于stack exchange,提问作者Anirban Saha
相关产品推荐
相关产品推荐

