如何为Pydantic的__root__字段添加正则约束并自定义ValidationError信息?
解决方案
要实现对__root__字段字典键的正则校验,并返回Pydantic风格的标准错误响应,无需在接口层手动处理序列化和异常,直接通过Pydantic的自定义校验器即可完成。
方法一:使用Pydantic Validator(兼容v1/v2)
1. 定义带校验的模型
from pydantic import BaseModel, validator, ValidationError from typing import Dict import re # 示例CarData模型,可根据实际需求修改 class CarData(BaseModel): model: str year: int class Cars(BaseModel): __root__: Dict[str, CarData] @validator("__root__") def validate_numeric_keys(cls, value): # 定义键的正则规则:仅允许纯数字 key_pattern = re.compile(r'^\d+$') # 筛选不符合规则的键 invalid_keys = [key for key in value.keys() if not key_pattern.match(key)] if invalid_keys: # 抛出自定义校验错误,指定错误详情 raise ValidationError( errors=[ { "loc": ["__root__"], "msg": "hey there, you can only use digits!", "type": "value_error.dict_key_invalid" } ], model=cls ) return value
2. 简化接口逻辑
接口无需手动处理序列化和异常捕获,FastAPI会自动处理Pydantic的校验错误并返回标准格式响应:
from fastapi import FastAPI, Body app = FastAPI() @app.post("/cars") async def get_cars(cars: Cars = Body(...)): return 'works'
方法二:使用Annotated + AfterValidator(Pydantic v2推荐)
如果你使用Pydantic v2,更推荐用Annotated结合AfterValidator的方式,代码结构更清晰:
from pydantic import BaseModel, AfterValidator from typing import Dict, Annotated import re class CarData(BaseModel): model: str year: int def validate_numeric_keys(value: Dict[str, CarData]) -> Dict[str, CarData]: key_pattern = re.compile(r'^\d+$') for key in value.keys(): if not key_pattern.match(key): raise ValueError("hey there, you can only use digits!") return value class Cars(BaseModel): __root__: Annotated[Dict[str, CarData], AfterValidator(validate_numeric_keys)]
接口部分和方法一完全一致,无需修改。
效果演示
当请求体包含非数字键(如{"abc": {"model": "Tesla", "year": 2023}})时,接口会自动返回以下标准格式的错误响应:
{ "detail": [ { "loc": [ "body", "__root__" ], "msg": "hey there, you can only use digits!", "type": "value_error.dict_key_invalid" } ] }
内容的提问来源于stack exchange,提问作者avnav99
相关产品推荐
相关产品推荐

