Pydantic v2 入门教程:模型、字段、验证器

简介: 本文详解 Pydantic v2(Python 3.10+)核心用法:模型定义、字段约束、自定义验证器(field/model)、嵌套/递归结构、序列化控制及 JSON Schema 生成,所有示例完整可运行,助你构建健壮数据验证与序列化逻辑。

本问将覆盖 API 的每个核心部分:定义模型、约束字段、写验证器、组合嵌套结构、控制序列化。所有示例基于 Pydantic v2Python 3.10+,每个清单完整可运行。

用 BaseModel 定义模型

Pydantic 的核心就是

BaseModel

。继承

BaseModel

,用注解声明字段。Pydantic 在类创建时检查注解、构建校验 schema,每次实例化时用它。

无默认值的就是必填。有默认值或声明为

T | None

且默认

None

的就是可选。

 from pydantic import BaseModel  

class Address(BaseModel):  
    street: str  
    city: str  
    state: str  
    zip_code: str  
    country: str = "US"           # 可选,默认 "US"  
    apartment: str | None = None  # 可选,默认 None  

addr = Address(  
    street="123 Main St", city="Springfield", state="IL", zip_code="62704",  
)  
print(addr)  
 # street='123 Main St' city='Springfield' state='IL' zip_code='62704' country='US' apartment=None

注解加默认值不够用时上

Field()

。给字段附加元数据、约束和文档。

 from pydantic import BaseModel, Field  

class Product(BaseModel):  
    name: str = Field(min_length=1, max_length=200, title="Product Name",  
                      description="商品显示名称", examples=["Widget Pro"])  
    sku: str = Field(pattern=r"^[A-Z]{2,4}-\d{4,8}$",  
                     description="库存单位,格式 'XX-0000'", examples=["WP-12345"])  
    price: float = Field(gt=0, le=999_999.99, description="美元价格,必须为正")  
    quantity: int = Field(default=0, ge=0, description="库存数量,不可为负")  
    category: str = Field(validation_alias="product_category",  
                          description="来自目录系统的产品类别")  

product = Product(name="Widget Pro", sku="WP-12345", price=29.99,  
                  quantity=150, product_category="Electronics")  
 print(product.category)  # Electronics

设了

validation_alias

后,Pydantic 只接受别名作为输入。想同接收字段名需要加

model_config = ConfigDict(populate_by_name=True)

Annotated 风格复用约束

 from typing import Annotated  
from pydantic import BaseModel, Field  

PositiveInt = Annotated[int, Field(gt=0)]  
ShortStr = Annotated[str, Field(min_length=1, max_length=100)]  

class Widget(BaseModel):  
    quantity: PositiveInt  
     name: ShortStr

两种风格校验行为相同,跨模型共享类型时用

Annotated

类型强制转换与严格模式,默认宽松模式:兼容类型自动转,不拒绝。这对 JSON 这种全部是字符串时很实用。

 event = Event(name="PyCon", attendees="500", event_date="2025-05-15")  
 # "500" 自动转 int,"2025-05-15" 自动转 date

模型级严格模式:设

model_config = ConfigDict(strict=True)

。字段级严格模式:

Field(strict=True)

Annotated[int, Strict()]

数据源已是强类型(内部 Python 调用、强类型数据库驱动)时用严格模式。解析 JSON 或表单数据时保持宽松。

验证器:field_validator 和 model_validator

Pydantic 内置类型系统和

Field()

约束覆盖了大部分校验需求。不够时也可以上自定义验证器。

@field_validator

有四种模式:

  • mode='after'(默认):内置换完才跑,收到的是已解析的带类型值。
  • mode='before':在内置校验前跑,收原始输入。
  • mode='wrap':包裹内置校验,可做日志或错误转译。
  • mode='plain':完全替代内置校验。
 class User(BaseModel):  
    username: str = Field(min_length=3, max_length=30)  
    email: str  
    @field_validator("username", mode="before")  
    @classmethod  
    def normalize_username(cls, v: object) -> str:  
        if not isinstance(v, str):  
            raise ValueError("Username must be a string")  
        return v.strip().lower()  
    @field_validator("email", mode="after")  
    @classmethod  
    def validate_email_domain(cls, v: str) -> str:  
        if "@" not in v:  
            raise ValueError("Invalid email: missing '@'")  
         return v
mode='before'

先跑,去掉空白后的值

"alice_99"

才是 Pydantic 检查

min_length=3

的对象。

验证依赖多字段时用

@model_validator

 class DateRange(BaseModel):  
    start: date  
    end: date  
    label: str | None = None  
    @model_validator(mode="after")  
    def check_start_before_end(self) -> DateRange:  
        if self.start >= self.end:  
            raise ValueError(f"'start' ({self.start}) must be before 'end' ({self.end})")  
         return self

After 模式验证器必须

return self

,忘掉就返回

None

,对不可空字段会报错

ValidationError

mode='before'

模型验证器时类方法,收原始数据,能在任何字段校验前重塑输入:

 class Coordinate(BaseModel):  
    x: float  
    y: float  
    @model_validator(mode="before")  
    @classmethod  
    def accept_tuple(cls, data: object) -> object:  
        if isinstance(data, (list, tuple)) and len(data) == 2:  
            return {"x": data[0], "y": data[1]}  
        return data  

 print(Coordinate.model_validate((3.0, 4.0)))  # x=3.0 y=4.0

ValidationInfo 验证上下文

info.context

能把每次调用的数据(如用户权限级别)传进验证器,不用加到模型本身:

 class Discount(BaseModel):  
    price: float  
    discount_pct: float  
    @field_validator("discount_pct", mode="after")  
    @classmethod  
    def cap_discount(cls, v: float, info: ValidationInfo) -> float:  
        max_discount = (info.context or {}).get("max_discount", 50.0)  
        if v > max_discount:  
            raise ValueError(f"Discount cannot exceed {max_discount}%")  
        return v  

Discount.model_validate(  
    {"price": 100.0, "discount_pct": 30.0},  
    context={"max_discount": 20.0},  
 )

自定义序列化器

@field_serializer

控制导出格式:

 class LogEntry(BaseModel):  
     message: str  
     timestamp: datetime  
     @field_serializer("timestamp")  
     def serialize_timestamp(self, v: datetime) -> str:  
         if v.tzinfo is None:  
             v = v.replace(tzinfo=timezone.utc)  
         return v.astimezone(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")

嵌套模型与递归结构

一个模型直接作为另一个模型字段的类型注解,天然嵌套:

 class Employee(BaseModel):  
    name: str  
    title: str  
    employee_id: int = Field(gt=0)  

class Department(BaseModel):  
    name: str  
    head: Employee  
    members: list[Employee] = []  

class Company(BaseModel):  
    name: str  
    founded: int  
     departments: list[Department]

每个嵌套 dict 针对对应模型校验。Bob 的

employee_id

"not_a_number"

,错误会指到

departments -> 0 -> members -> 0 -> employee_id

自引用模型用

from __future__ import annotations

 class TreeNode(BaseModel):  
     value: str  
     children: list[TreeNode] = []

model_dump 和 model_dump_json

这俩有三种输出方法:

  • model_dump() 出原生 Python 类型的 dict。
  • model_dump(mode='json') 出 JSON 兼容值。
  • model_dump_json() 直接出 JSON 字符串,绕过 json.dumps() 更快。

支持

exclude_unset

exclude_none

include

exclude_defaults

等过滤参数。

输入方面:

model_validate()

解析 dict,

model_validate_json()

解析原始 JSON 字符串,直接调 Rust 核心更快。

三种别名:

alias

(输入输出都用)、

validation_alias

(仅输入)、

serialization_alias

(仅输出)。

AliasPath

AliasChoices

支持嵌套访问和多个候选名。

model_dump()

model_dump_json()

都接受相同的过滤参数:

JSON Schema 生成

Item.model_json_schema()

输出 JSON Schema,

Field()

里的

title

description

examples

、约束全自动流入。

Pydantic Dataclasses 和 TypeAdapter

Pydantic dataclasses 和

BaseModel

一样支持验证器和约束,但没有

model_dump()

等方法。序列化需通过

TypeAdapter

包装。

TypeAdapter

不需要模型类就能验证独立类型:

 int_list_adapter = TypeAdapter(list[int])  
 int_list_adapter.validate_python(["1", "2", "3"])  # [1, 2, 3]  
 int_list_adapter.validate_json('[4, 5, 6]')  # [4, 5, 6]

适合:验证函数参数、验证集合类型、为 API 类型生成 JSON Schema。

总结

最后用一些FAQ结束这篇文章:

field_validator 还是 model_validator? 单字段用

@field_validator

,精确、快。需要同时访问多个字段时用

@model_validator(mode='after')

BaseModel 和 @dataclass 的区别? BaseModel 全功能。@dataclass 用熟悉语法但不带模型方法,序列化需 TypeAdapter。

如何让字段可选带默认值?

field: str = "default"

field: str | None = None

不建模型怎么验证 JSON?

TypeAdapter(list[int]).validate_json('[1,2,3]')

传了别名验证器不跑?

validation_alias

默认只吃别名。加

ConfigDict(populate_by_name=True)

https://avoid.overfit.cn/post/04f8ff4a442640cc9b2ca1a57fa7c2e7

by ez7

目录
相关文章
|
1月前
|
机器学习/深度学习 人工智能 监控
8类工地安全防护用品检测5200张数据集分享
本数据集含5200张真实工地实景图像,精细标注8类安全目标(安全帽、反光背心、施工人员等),YOLO格式,开箱即用。适用于智慧工地监管、PPE合规检测及YOLOv5-v11等模型训练,助力工业安防与目标检测研究。
|
1月前
|
人工智能 安全 前端开发
10|Agent Harness 的未来:从代码助手到工程协作系统
AI编程正迈入第三阶段——Agent Harness:AI不再仅补全代码或回答问题,而是深度融入研发全流程——读仓库、改文件、跑测试、连工具、协作者。未来核心在于“可治理的工程协作”,而非单纯自动化。(239字)
191 8
|
4天前
|
人工智能 监控 测试技术
银行业AI架构:从裸调API到六层技能体系
# 银行AI智能体架构实战:从单体到Skill协同的技术演进 ## 痛点:银行IT架构的三重困境 走在任何一家银行的科技部走廊里,你都能听到同样的叹息:系统又慢了、需求又排不上、监管又来查了。这不是某一家银行的困境,而是整个银行业IT架构的共性问题。我们把它拆解为三重困境。 **困境一:单体系
|
29天前
|
JSON 物联网 计算机视觉
微调LocateAnything-3B 实现超高密度的目标检测
本文介绍如何微调NVIDIA LocateAnything-3B模型,应对300+密集重叠种子的精准定位难题。依托并行框解码(PBD)与半监督Pipeline(点标注→SAM2转框→YOLO伪标→定向微调),大幅降低人工成本,实现高精度、可落地的密集目标检测方案。
445 0
微调LocateAnything-3B 实现超高密度的目标检测
|
19天前
|
前端开发 安全 JavaScript
Harness Engineering 实践案例:如何Agent 写一份行为规范
本文展示Harness Engineering落地实践:通过`AGENTS.md`(行为总纲)、`ARCHITECTURE.md`(系统骨架)等结构化文档,为编码Agent建立可追溯、可审计、防幻觉的工作规范,实现RAG+微调系统的可控开发。
169 4
Harness Engineering 实践案例:如何Agent 写一份行为规范
|
1月前
|
数据采集 人工智能 分布式计算
多Agent集群中的"情报官"设计:为什么系统需要一个RDD
在多Agent系统中,信息采集环节的失误往往是级联错误的根源。本文从行业实践和学术研究两个维度,论证了专职情报采集Agent的必要性,并详细解析了枢衡RDD(资源探测)的五大架构设计原则,包括与CAD的对抗性协作机制等。最后提供了一套可落地的自检清单,帮助开发者判断自己的Agent集群是否需要引入专职情报官角色。
|
1月前
|
人工智能 安全 前端开发
面试官问:什么是 Harness 工程?AI Agent 时代,测试人必须补上的新能力
Harness工程是AI Agent时代的“工作台”,聚焦为其构建稳定、可控、可验证的工程环境。它涵盖上下文管理、工具调用、沙箱权限、测试验证、日志观测与反馈回路,解决Agent在真实项目中因缺上下文、缺工具、缺反馈、缺边界导致的失控问题。本质是让Agent“能做事、做得对、出错可修复”。
|
1月前
|
C# C语言 C++
VS2019下载地址和安装使用图文教程(附官网安装包)
Visual Studio 2019是微软2019年发布的稳定IDE,支持C/C++、C#等语言。Community版免费且功能完整,安装轻量、兼容性强,尤其适合老项目维护与低配设备。文中详述了下载、安装及用其编写运行C程序的完整流程。(239字)