FastAPI中BaseModel如何处理键为数字字符串的嵌套JSON数据校验
报错原因
Python语法本身不允许将纯数字、数字开头的字符串作为类属性/变量名,你直接在类中写0: float、400: D_0123属于语法错误,和FastAPI、Pydantic的功能无关。另外你原有代码中Dict[D_0123]的写法也不符合Python类型标注规范,Dict泛型需要同时指定键类型和值类型,比如Dict[str, D_0123]。
你的需求完全可以实现,两种常用解决方法如下:
方法1:固定键场景用Field指定别名(推荐,可完整校验结构)
如果JSON中的键是固定的(比如固定只有"0"、"400"这些键),可以用Pydantic的Field参数指定别名,自定义合法的Python属性名做映射即可。
完整可运行的模型定义示例如下:
from pydantic import BaseModel, Field, ConfigDict # 对应d下400里的结构:键为"0"-"3",值为float class DValue(BaseModel): model_config = ConfigDict(populate_by_alias=True) v0: float = Field(alias="0") v1: float = Field(alias="1") v2: float = Field(alias="2") v3: float = Field(alias="3") # 对应b下c的结构:键为"0",值为字符串 class CValue(BaseModel): model_config = ConfigDict(populate_by_alias=True) v0: str = Field(alias="0") # 对应b下400的结构:键为"0",值为整数 class B400Value(BaseModel): model_config = ConfigDict(populate_by_alias=True) v0: int = Field(alias="0") # 对应a下b的结构 class BValue(BaseModel): model_config = ConfigDict(populate_by_alias=True) c: CValue v400: B400Value = Field(alias="400") # 对应a下d的结构 class DStructure(BaseModel): model_config = ConfigDict(populate_by_alias=True) v400: DValue = Field(alias="400") # 对应a的结构 class AValue(BaseModel): b: BValue d: DStructure # 最终的请求体模型 class Item(BaseModel): name: str a: AValue
使用说明:
- 接口接收的JSON不需要做任何修改,还是按你原来的结构传"0"、"400"这些键即可,Pydantic会自动完成别名映射
- 你在业务代码中访问对应值时,用自定义的合法属性名即可,比如
item.a.d.v400.v0就能拿到d下400里"0"对应的值56.3 - 如果你用的是Pydantic V1,把
model_config那行替换成类内部的Config类即可:class Config: allow_population_by_field_name = True
方法2:动态键场景用Dict类型
如果JSON中的数字键不固定(比如除了400还有200、300等任意数字键),不需要严格校验每个键的存在,直接用Dict类型定义即可:
from pydantic import BaseModel from typing import Dict, Union class Item(BaseModel): name: str # 直接嵌套Dict定义结构,键为字符串,值对应对应结构即可 a: Dict[str, Dict[str, Union[Dict[str, str], Dict[str, int], Dict[str, Dict[str, float]]]]]
这种方式灵活度更高,但结构校验的严格度低于方法1。
内容的提问来源于stack exchange,提问作者Madari
相关产品推荐
相关产品推荐

