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

BeforeValidator 或模型字段类型本身该干的事。
field_validator 接收的是已初步解析后的值(比如 str 字段收到的就是字符串,不是原始 JSON 字符串)ValueError/TypeError;返回其他类型会静默失败或触发后续类型错误@field_validator 按定义顺序执行,前一个的返回值是后一个的输入它只在调用 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 里把 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
这是容易被忽略的坑。当 @field_serializer 返回 None,Pydantic 默认在 model_dump() 中跳过该字段(类似 exclude_unset=True 的行为),而不是保留 null。
null,必须返回 None 并设置 when_used='always' + 显式传 exclude_none=False
None,改用空字符串、默认值或专门的标记对象print() 在 serializer 里确认是否被调用——它只在序列化时触发,赋值时完全不执行