You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 12:25:30