field_validator用于校验并可选修改已解析字段值,不负责类型转换;它在解析阶段运行,接收同类型输入、返回同类型输出,多个按定义顺序执行,不可做I/O;field_serializer则仅在序列化时控制输出格式,与输入校验无关。

field_validator 用来改值或抛错,不是做类型转换的
它在数据解析阶段运行,作用是校验并可选地修改字段原始输入值。比如把字符串转成小写、检查邮箱格式、拒绝空字符串等。注意它不负责类型转换——那是 BeforeValidator 或模型字段类型本身该干的事。
-
field_validator接收的是已初步解析后的值(比如str字段收到的就是字符串,不是原始 JSON 字符串) - 必须返回同类型的值,或抛出
ValueError/TypeError;返回其他类型会静默失败或触发后续类型错误 - 多个
@field_validator按定义顺序执行,前一个的返回值是后一个的输入 - 别在里面做 I/O 或耗时操作,它属于解析路径,影响初始化性能
field_serializer 控制输出,不影响输入和校验
它只在调用 model.model_dump()、model.model_dump_json() 或 print(model) 等序列化场景触发,对字段赋值、校验、内部存储完全无感。典型用途是脱敏、格式标准化、添加计算字段。
- 默认不启用,需显式传
mode='json'或mode='python'才生效;不加mode参数时不会被调用 - 接收的是字段当前存储的值(比如一个
datetime对象),不是原始输入 - 可以返回任意可序列化的类型(如
str替代datetime),但要确保与return_type注解一致,否则 IDE 和类型检查可能报错 - 如果同时定义了
@field_validator和@field_serializer,它们互不干扰:一个管“进”,一个管“出”
别把 field_validator 当成 before_validator 用
常见误操作是想在 field_validator 里把 str 转成 int,结果报 Input should be a valid integer。这是因为 Pydantic v2 的解析流程是:原始输入 → 类型转换(由字段类型驱动)→ field_validator。类型转换失败发生在 validator 之前,根本进不到你的函数里。
- 真需要预处理原始输入(比如把
"123"字符串转成int),得用BeforeValidator,配合Annotated - 例如:
age: Annotated[int, BeforeValidator(lambda x: int(x) if isinstance(x, str) else x)] -
field_validator适合在类型已确定的前提下做业务逻辑校验,比如if value
serializer 返回 None 会导致字段被忽略(除非显式设 exclude_none=False)
这是容易被忽略的坑。当 @field_serializer 返回 None,Pydantic 默认在 model_dump() 中跳过该字段(类似 exclude_unset=True 的行为),而不是保留 null。
- 若需输出
null,必须返回None并设置when_used='always'+ 显式传exclude_none=False - 更稳妥的做法是避免返回
None,改用空字符串、默认值或专门的标记对象 - 调试时可用
print()在 serializer 里确认是否被调用——它只在序列化时触发,赋值时完全不执行










