
本文介绍如何在 Pydantic v2+ 中为嵌套列表字段(即 list[list[str]])施加子列表长度校验,确保每个内层列表长度 ≥2,同时允许外层为空;借助 annotated_types.MinLen 与 typing.Annotated 实现简洁、类型安全的声明式验证。
本文介绍如何在 pydantic v2+ 中为嵌套列表字段(即 `list[list[str]]`)施加子列表长度校验,确保每个内层列表长度 ≥2,同时允许外层为空;借助 `annotated_types.minlen` 与 `typing.annotated` 实现简洁、类型安全的声明式验证。
在 Pydantic 中,对嵌套结构(如列表中的列表)施加细粒度约束(例如要求每个子列表至少包含两个元素)不能仅靠内置的 conlist 实现——因为 conlist 作用于最外层容器,无法直接约束内层列表的长度。正确方案是使用 typing.Annotated 结合第三方类型注解库 annotated-types 提供的 MinLen,将长度约束“注入”到子列表的类型声明中。
✅ 正确实现方式
首先安装依赖(若未安装):
pip install annotated-types
然后定义模型如下:
from typing import Annotated
from annotated_types import MinLen
from pydantic import BaseModel
class SubListModel(BaseModel):
my_list: list[Annotated[list[str], MinLen(2)]]
该定义语义清晰:
- my_list 是一个字符串列表的列表;
- 每个内层 list[str] 都被标注为 至少含 2 个元素(MinLen(2));
- 外层 list[...] 本身无长度限制,因此空列表 [] 完全合法。
✅ 验证行为示例
# ✅ 合法输入 SubListModel(my_list=[]) # 空外层 → 通过 SubListModel(my_list=[["a", "b"], ["x", "y", "z"]]) # 所有子列表长度 ≥2 → 通过 # ❌ 非法输入(触发 ValidationError) SubListModel(my_list=[[]]) # 子列表长度为 0 → 失败 SubListModel(my_list=[["a"], ["b", "c"]]) # 首个子列表长度为 1 → 失败
⚠️ 注意事项:
- MinLen 是运行时验证器,由 Pydantic 自动识别并集成进验证流程,无需手动调用;
- 不要尝试嵌套 conlist(如 conlist(conlist(str, min_length=2))),Pydantic v2 不支持此类嵌套约束语法;
- Annotated 是 PEP 593 标准特性,兼容 Pydantic v2.x 所有稳定版本(推荐 ≥2.6);
- 若需同时约束外层列表长度(如“至少 1 个子列表”),可额外叠加 MinLen 到外层:Annotated[list[...], MinLen(1)]。
该方案兼顾类型提示完整性、运行时强校验与代码可读性,是 Pydantic 生态中处理嵌套容器约束的推荐实践。











