pydantic v2 移除了 __root__,改用 rootmodel;field(default=none) 不再表示可选,需用 default=...;dict() 替换为 model_dump();@validator 升级为 @field_validator 和 @model_validator。

pydantic.BaseModel 不再支持 __root__ 字段
很多老项目用 __root__ 实现单值包装(比如只校验一个 str 或 int),v2 直接删了这个机制。不是弃用警告,是运行时就报错:TypeError: __root__ is not supported in Pydantic v2。
改法很简单:用 RootModel 替代。
- 原写法:
class Name(str, BaseModel):<br> __root__: str
- v2 正确写法:
from pydantic import RootModel<br><br>class Name(RootModel[str]):<br> pass
-
RootModel的root属性就是那个单值,访问方式从inst.__root__变成inst.root - 注意:不能继承
BaseModel同时定义root字段,会冲突
Field 默认值逻辑变了:None 不再等价于“未设置”
v1 里 Field(default=None) 表示字段可选、默认为 None;v2 里这会被当成显式设了默认值,导致该字段不再算“可选”,JSON Schema 里不会标 "nullable": true,OpenAPI 文档也容易出错。
真正想表达“可选且无默认值”,必须用 Field(default=...)(三个点)或 Field(default=None, default_factory=lambda: None) —— 但后者不推荐,语义不清。
立即学习“Python免费学习笔记(深入)”;
- ✅ 正确(可选,无默认值):
name: str | None = Field(default=...) - ❌ 错误(变成必填,默认值为
None):name: str | None = Field(default=None) - 如果字段类型已是
Optional[str](即str | None),又写了default=...,它才是真正的可选;否则即使类型含None,没配default=...就是必填
model_dump() 和 dict() 彻底不兼容
v1 的 inst.dict() 在 v2 里已移除,直接调用会抛 AttributeError。替代方法是 inst.model_dump(),但它行为更严格:默认不包含 None 值字段(exclude_none=True),也不递归序列化嵌套模型(除非显式开 serialize_as_any=True)。
- 要完全复刻 v1 的
dict()行为,得写:inst.model_dump(exclude_unset=False, exclude_defaults=False, exclude_none=False) - 但多数场景不需要这么宽松 —— 比如 FastAPI 返回响应时,默认
model_dump()就够用;手动调试才需要展开所有字段 - 顺带一提:
model_dump_json()是新接口,别再用json.dumps(inst.dict()),那会漏掉自定义序列化逻辑
验证器写法迁移:从 @validator 到 @field_validator 和 @model_validator
@validator 装饰器在 v2 完全失效,连 import 都会报错。新机制拆得更细:字段级用 @field_validator,整个模型级用 @model_validator,而且签名、参数名、执行时机都有调整。
- 旧写法:
@validator('age')<br>def check_age(cls, v): ... - 新写法:
@field_validator('age')<br>def check_age(cls, v): ...(函数签名不变,但装饰器名和 import 路径变了) - 注意:v2 中
@field_validator默认在类型转换后执行,如果想在原始输入上校验(比如字符串长度),得加参数mode='before' -
@model_validator(mode='before')用来处理整个输入字典,适合做字段间依赖校验,但别在里面改values字典 —— 应该返回新字典
Optional[T] 和 Union[T, None] 可能触发奇怪的解析失败;还有 validate_assignment=True 的行为变化,这些细节不写进字段定义、只靠文档很难发现。改的时候最好打开 pydantic.warnings 日志,把 warning 当 error 处理。










