pydantic v2作为Python中主流的数据校验与模型定义库,提供了灵活的字段自定义处理能力,其中field_validator和field_serializer是最常用的两个装饰器,二者分别承担数据校验和序列化转换的职责,功能和使用场景有明显差异。

field_validator:字段校验装饰器
field_validator用于在模型实例化阶段对输入字段的值进行校验和预处理,当输入数据不符合要求时可以抛出校验错误,也可以对输入值做格式化处理后再赋值给字段。
基础使用方式
使用field_validator装饰器时需要指定要校验的字段名称,装饰器函数的第一个参数是cls,第二个参数是要校验的字段值,函数返回处理后的字段值。
from pydantic import BaseModel, field_validator, ValidationError
class UserModel(BaseModel):
username: str
age: int
@field_validator("username")
def check_username(cls, value):
# 校验用户名长度
if len(value) < 3:
raise ValueError("用户名长度不能小于3位")
# 去除首尾空格
return value.strip()
@field_validator("age")
def check_age(cls, value):
if value < 0 or value > 120:
raise ValueError("年龄必须在0到120之间")
return value
# 测试正常数据
try:
user = UserModel(username=" test ", age=25)
print(user.username) # 输出 test
print(user.age) # 输出 25
except ValidationError as e:
print(e)
# 测试异常数据
try:
user = UserModel(username="ab", age=150)
except ValidationError as e:
print(e)
多字段校验与模式配置
field_validator支持同时校验多个字段,也可以通过mode参数配置校验触发时机,默认mode为before,即在类型转换前执行校验。
from pydantic import BaseModel, field_validator
class ProductModel(BaseModel):
price: float
discount: float
@field_validator("price", "discount")
def check_positive(cls, value):
if value < 0:
raise ValueError("价格和折扣不能为负数")
return value
@field_validator("discount", mode="after")
def check_discount_lt_price(cls, value, info):
# after模式下可以获取其他字段的值
if info.data.get("price") and value > info.data["price"]:
raise ValueError("折扣不能大于商品价格")
return value
# 测试校验逻辑
product = ProductModel(price=100.0, discount=30.0)
print(product.discount) # 输出 30.0
field_serializer:字段序列化装饰器
field_serializer用于在模型序列化阶段(比如调用model_dump、model_dump_json方法时)对字段值进行转换处理,不会影响模型实例化时的字段值,只影响输出结果。
基础使用方式
field_serializer装饰器同样需要指定要处理的字段名称,装饰器函数的第一个参数是字段值,返回序列化后的结果。
from pydantic import BaseModel, field_serializer
from datetime import datetime
class OrderModel(BaseModel):
order_id: str
create_time: datetime
@field_serializer("create_time")
def serialize_time(self, value):
# 将datetime转换为指定格式的字符串
return value.strftime("%Y-%m-%d %H:%M:%S")
@field_serializer("order_id")
def serialize_order_id(self, value):
# 给订单号添加前缀
return f"ORD_{value}"
order = OrderModel(
order_id="123456",
create_time=datetime(2024, 5, 20, 14, 30, 0)
)
# 序列化输出
print(order.model_dump())
# 输出 {'order_id': 'ORD_123456', 'create_time': '2024-05-20 14:30:00'}
print(order.model_dump_json())
# 输出 {"order_id":"ORD_123456","create_time":"2024-05-20 14:30:00"}
序列化时的上下文控制
field_serializer支持通过context参数传递序列化上下文,实现不同场景下的差异化序列化逻辑。
from pydantic import BaseModel, field_serializer
class ArticleModel(BaseModel):
title: str
content: str
@field_serializer("content")
def serialize_content(self, value, info):
# 根据上下文判断是否截断内容
context = info.context
if context and context.get("is_summary"):
return value[:50] + "..." if len(value) > 50 else value
return value
article = ArticleModel(
title="pydantic教程",
content="这是一篇关于pydantic v2自定义字段处理的详细教程,内容包含field_validator和field_serializer的用法"
)
# 普通序列化
print(article.model_dump())
# 带上下文的序列化
print(article.model_dump(context={"is_summary": True}))
field_validator与field_serializer的核心区别
两者虽然都是字段处理的装饰器,但适用场景和功能有本质不同,具体差异如下:
| 对比维度 | field_validator | field_serializer |
|---|---|---|
| 触发时机 | 模型实例化、字段赋值阶段 | 模型序列化(model_dump、model_dump_json)阶段 |
| 核心作用 | 校验输入数据合法性,预处理输入值 | 转换字段输出格式,适配不同输出场景 |
| 是否影响原字段值 | 会,返回的处理后值会赋给字段 | 不会,仅影响序列化输出结果 |
| 错误处理 | 校验失败抛出ValidationError | 序列化失败抛出序列化相关错误 |
| 典型场景 | 数据格式校验、类型转换、取值范围校验 | 时间格式化、字段加密、输出内容截断 |
组合使用场景示例
在实际开发中,经常需要同时使用两个装饰器完成完整的数据处理流程,比如下面的用户模型,既需要校验邮箱格式,又需要在输出时脱敏处理。
from pydantic import BaseModel, field_validator, field_serializer
import re
class UserProfileModel(BaseModel):
email: str
@field_validator("email")
def validate_email(cls, value):
# 校验邮箱格式
pattern = r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$"
if not re.match(pattern, value):
raise ValueError("邮箱格式不正确")
return value
@field_serializer("email")
def serialize_email(self, value):
# 邮箱脱敏处理,保留前3位和域名部分
prefix, domain = value.split("@")
masked_prefix = prefix[:3] + "***"
return f"{masked_prefix}@{domain}"
# 测试完整流程
user = UserProfileModel(email="test123@ippipp.com")
print(user.email) # 输出 test123@ippipp.com(原字段值不变)
print(user.model_dump()) # 输出 {'email': 'tes***@ippipp.com'}(序列化后脱敏)
通过合理搭配field_validator和field_serializer,可以满足pydantic v2中绝大多数自定义字段处理的需求,让数据模型的校验和输出逻辑更加清晰可控。
pydantic_v2field_validatorfield_serializer自定义字段验证修改时间:2026-06-14 19:54:39