如何动态基于自定义Pydantic模型校验目标对象数据?
Pydantic泛型结构通用校验实现
场景说明
现有代码通过Pydantic定义模型,手动遍历列表逐个实例化模型完成接口返回数据校验,示例代码如下:
class Name(BaseModel): name_id: str first_name: str last_name: str def get_all_names() -> List[Name]: names = [] try: # 该接口返回NAME对象列表 names = requests.get("some-url") # 现有校验逻辑:逐个实例化模型验证格式 validate_name_objects = [Name(**each_name_object) for each_name_object in names] except Exception as e: # 请求错误、校验错误都会被捕获并记录日志 logger.info(f"log this error (could be requests error, could be validation error: {e}") return names
FastAPI本身会自动读取函数签名的返回值类型提示(比如本例中的List[Name]),响应数据不符合类型定义时自动抛出异常。现在需要在代码多处位置对不同自定义Pydantic模型执行同类校验,要实现一个通用校验函数:
- 第一个入参为待匹配的自定义类型,支持任意Pydantic模型组合结构,包括
List[自定义模型]、Dict[str, 自定义模型]等泛型形式 - 第二个入参为待校验的载荷数据
- 调用后直接完成数据合规性校验,不符合定义则抛出校验错误
之前查到的Pydantic校验装饰器仅支持校验指定函数的输入参数,无法动态传入自定义模型完成校验。
实现方案
直接使用Pydantic内置的parse_obj_as工具函数即可满足需求,调用方式完全匹配预期:
from pydantic import parse_obj_as # 替换原有手动遍历校验的逻辑 validate_name_objects = parse_obj_as(List[Name], names)
注意:Pydantic本质是解析库而非纯校验库,校验过程中会对符合转换规则的数据自动做类型转换
该工具支持所有Pydantic兼容的类型结构,以下是不同场景的校验示例:
原生Python类型校验
from typing import Dict from pydantic import parse_obj_as items = parse_obj_as(Dict[int, str], {"asdasd": "23232"}) print(items)
数据不符合类型定义时会抛出预期的ValidationError:
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "pydantic/tools.py", line 35, in pydantic.tools.parse_obj_as File "pydantic/main.py", line 406, in pydantic.main.BaseModel.__init__ pydantic.error_wrappers.ValidationError: 1 validation error for ParsingModel[Dict] __root__ -> __key__ value is not a valid integer (type=type_error.integer)
自定义模型校验
from typing import List, Dict from pydantic import BaseModel, parse_obj_as class Item(BaseModel): id: int name: str items = parse_obj_as(Dict[int, Item], {1: "asdfasdasf"}) print(items)
不符合模型定义时抛出对应错误:
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "pydantic/tools.py", line 35, in pydantic.tools.parse_obj_as File "pydantic/main.py", line 406, in pydantic.main.BaseModel.__init__ pydantic.error_wrappers.ValidationError: 1 validation error for ParsingModel[Dict] __root__ -> 1 value is not a valid dict (type=type_error.dict)
复杂嵌套泛型结构校验
from typing import List, Dict, Tuple, Optional from pydantic import BaseModel, parse_obj_as class Item(BaseModel): id: int name: str items = parse_obj_as(Dict[Tuple[str, Optional[float], Optional[float]], Item], {(1, "123fdsfds", None): {'id': 1, 'name': 'My Item'}}) print(items)
嵌套结构中任意层级不符合类型定义都会抛出精准的错误信息:
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "pydantic/tools.py", line 35, in pydantic.tools.parse_obj_as File "pydantic/main.py", line 406, in pydantic.main.BaseModel.__init__ pydantic.error_wrappers.ValidationError: 1 validation error for ParsingModel[Dict] __root__ -> __key__ -> 1 value is not a valid float (type=type_error.float)
内容的提问来源于stack exchange,提问作者raghavsikaria
相关产品推荐
相关产品推荐

