
本文介绍如何使用 Pydantic 结合 annotated-types 为嵌套列表(即列表中的字符串子列表)设置子列表最小长度校验,确保每个内层列表至少包含两个元素,同时支持空外层列表。
本文介绍如何使用 pydantic 结合 `annotated-types` 为嵌套列表(即列表中的字符串子列表)设置子列表最小长度校验,确保每个内层列表至少包含两个元素,同时支持空外层列表。
在 Pydantic v2+ 中,直接对嵌套类型(如 list[list[str]])施加结构化约束(例如“每个子列表长度 ≥ 2”)无法通过原生 conlist 实现——因为 conlist 仅作用于最外层容器,不支持嵌套类型级别的长度限制。解决方案是借助 typing.Annotated 与第三方类型注解库 annotated-types,它提供了语义清晰、可组合的校验谓词(如 MinLen),并被 Pydantic 原生支持。
✅ 正确实现方式
from typing import Annotated
from annotated_types import MinLen
from pydantic import BaseModel
class SubListModel(BaseModel):
my_list: list[Annotated[list[str], MinLen(2)]]
此处 Annotated[list[str], MinLen(2)] 表示:每个子项必须是 list[str] 类型,且其长度不得小于 2。Pydantic 在解析时会自动对每个子列表执行 len() >= 2 校验。
✅ 验证行为说明
- ✅ SubListModel(my_list=[]):合法 —— 外层为空列表,无需校验子列表;
- ✅ SubListModel(my_list=[["a", "b"], ["x", "y", "z"]]):合法 —— 所有子列表长度 ≥ 2;
- ❌ SubListModel(my_list=[[]]):抛出 ValidationError —— 空子列表 len([]) == 0
- ❌ SubListModel(my_list=[["a"], ["b", "c"]]):抛出 ValidationError —— ["a"] 长度为 1,不满足约束。
⚠️ 注意事项
-
依赖安装:需显式安装 annotated-types(Pydantic 不自带):
pip install annotated-types
- 类型兼容性:MinLen 仅适用于支持 len() 的类型(如 list, str, tuple, bytes),对 set 或自定义类需确保实现了 __len__;
- 性能影响:每次模型实例化时均会对每个子列表调用 len(),对超大嵌套结构建议做前置过滤;
- 替代方案限制:若不用 annotated-types,也可通过 field(default_factory=...) + 自定义 @field_validator 实现,但代码更冗长且失去声明式简洁性。
综上,Annotated[list[str], MinLen(2)] 是目前最简洁、标准、可读性强的解决方案,完美契合 Pydantic 的现代类型注解哲学。











