首页 / FastAPI 入门教程 / 配置与序列化

FastAPI 入门教程

配置与序列化

本教程共 50 篇 · 第 21 篇 · 更新于 2026-08-12 · 约 7 分钟阅读

FastAPIFastAPI 入门教程Pydantic v2model_configmodel_dumpmodel_validate

本节目标:学会用 model_config 配置模型行为,用 model_dump、model_dump_json、model_validate 完成对象的导出与重建,并能从 ORM 对象加载数据。

模型不只是「收数据、校验」。实际开发中,你还要把模型变成字典、变成 JSON 字符串,或者反过来从一段数据重建模型。Pydantic v2 把这些能力收敛成几个统一的方法,并集中用 model_config 管理配置。

21-1 什么是序列化

「序列化」就是把内存里的 Python 对象,变成可以传输、存储的格式(比如字典、JSON 字符串)。「反序列化」则相反,把外面来的字典或 JSON 还原成模型对象。

from pydantic import BaseModel


class Item(BaseModel):
    name: str
    price: float

下面三个方法,就是你日常最常用的「出口」和「入口」。

21-2 model_dump() 导出为字典

model_dump() 把模型对象转成一个普通 Python 字典。

from pydantic import BaseModel


class Item(BaseModel):
    name: str
    price: float
    tax: float | None = None


item = Item(name="键盘", price=199.0, tax=0.1)
data = item.model_dump()
print(data)            # {'name': '键盘', 'price': 199.0, 'tax': 0.1}
print(type(data))      # <class 'dict'>

转成字典后,你就能把它喂给数据库驱动、日志组件,或自己再加工。注意这是 v2 写法,老的 .dict() 已经废弃,不要再用。

Note

严禁使用 Pydantic v1 的 .dict().json()。v2 对应物是 model_dump()model_dump_json()

21-3 model_dump_json() 导出为 JSON 字符串

如果你要直接返回 JSON 文本(比如给前端、写入文件),用 model_dump_json(),一步到位拿到字符串。

from pydantic import BaseModel


class Item(BaseModel):
    name: str
    price: float


item = Item(name="鼠标", price=99.0)
json_str = item.model_dump_json()
print(json_str)        # {"name":"鼠标","price":99.0}
print(type(json_str))  # <class 'str'>

这两个 dump 方法都接受实用参数:exclude={"tax"} 排除某些字段,include={"name"} 只保留指定字段,exclude_none=True 跳过值为 None 的字段。

item = Item(name="键盘", price=199.0, tax=None)
print(item.model_dump(exclude_none=True))   # {'name': '键盘', 'price': 199.0}

21-4 model_validate() 从字典重建模型

model_validate()model_dump() 的反操作:丢给它一个字典,它按模型规则校验并构造对象。

from pydantic import BaseModel, ValidationError


class Item(BaseModel):
    name: str
    price: float


raw = {"name": "显示器", "price": 899.0}
item = Item.model_validate(raw)
print(item.name)   # 显示器

如果字典不合法(比如价格传成字符串且转不了),它会抛出 ValidationError,和直接用 Item(...) 构造的行为一致。

Tip

从外部来源(数据库行、第三方接口)拿到的是普通字典时用 model_validate();如果你已经确定数据可信、想跳过校验提速,才考虑更底层的 model_construct()。初学阶段老实用 model_validate()

21-5 model_config 统一配置模型

Pydantic v2 把所有模型级配置收进 model_config,它是一个类属性。旧版那种 class Config: 的写法已经废弃,不要再写。

from pydantic import BaseModel, ConfigDict


class Item(BaseModel):
    model_config = ConfigDict(
        title="商品模型",
        extra="forbid",
    )

    name: str
    price: float

ConfigDict 里能放很多开关,下面挑最常用的讲。

21-6 from_attributes:从 ORM 对象加载

这是最常用的一项。数据库 ORM(如 SQLAlchemy)取出的对象,属性存在 .name.price 这种属性访问上,而不是字典的键。开启 from_attributes=True 后,model_validate() 就能直接从这种对象读数据。

from pydantic import BaseModel, ConfigDict


class PostResponse(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: int
    title: str


# 假设这是 SQLAlchemy 查出来的对象,不是字典
class PostORM:
    def __init__(self, id: int, title: str) -> None:
        self.id = id
        self.title = title


orm_obj = PostORM(id=1, title="我的第一篇文章")
post = PostResponse.model_validate(orm_obj)
print(post.title)   # 我的第一篇文章
Note

v1 里这叫 orm_mode = True,写在 class Config 中。v2 改名为 from_attributes=True,写在 model_config。这是迁移时最容易踩的坑,记住新写法。

21-7 几个实用配置项

  • extra="forbid":模型里没声明的字段,传进来就报错。可防止多余数据悄悄混进来。
  • extra="ignore":忽略多余字段(默认行为)。
  • str_strip_whitespace=True:自动去掉字符串首尾空格。
  • str_to_lower=True:把所有字符串转小写。
  • frozen=True:把模型变成「只读」,创建后不能改属性,类似不可变对象。
from pydantic import BaseModel, ConfigDict


class User(BaseModel):
    model_config = ConfigDict(str_strip_whitespace=True, extra="forbid")

    name: str
    age: int


u = User(name="  小红  ", age=18)
print(repr(u.name))   # '小红'(首尾空格已去掉)

21-8 在 FastAPI 里串起 ORM 与响应

真实流程是这样的:数据库取出 ORM 对象 → model_validate 转成响应模型 → FastAPI 自动序列化返回。配合 response_model 还能自动过滤字段。

from fastapi import FastAPI
from pydantic import BaseModel, ConfigDict

from typing import Any


class PostORM:
    def __init__(self, id: int, title: str, secret: str) -> None:
        self.id = id
        self.title = title
        self.secret = secret


class PostResponse(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: int
    title: str


app = FastAPI()


@app.get("/posts/{post_id}")
async def get_post(post_id: int) -> dict[str, Any]:
    orm_obj = PostORM(id=post_id, title="标题", secret="不能外泄")
    return PostResponse.model_validate(orm_obj).model_dump()

secret 字段不在 PostResponse 里,所以 model_dump() 的结果天然不含它——这就实现了「数据库字段与对外字段分离」。职责上:ORM 管数据库,Pydantic 管 API 契约。

21-9 model_dump 的进阶排除写法

excludeinclude 还能用嵌套字典语法,精确控制深层字段。比如模型里套了子模型,只想排除子模型的某个字段:

from pydantic import BaseModel


class Address(BaseModel):
    city: str
    secret_code: str


class User(BaseModel):
    name: str
    address: Address


u = User(name="小李", address=Address(city="北京", secret_code="X9"))
# 只排除 address 里的 secret_code
print(u.model_dump(exclude={"address": {"secret_code"}}))
# {'name': '小李', 'address': {'city': '北京'}}

这种「字典里套字典」的写法,键对应字段名,值为 True 或再嵌一层,非常灵活。

21-10 model_copy 拷贝并改值

想基于已有对象生成一个新对象(比如改一个字段),用 model_copy(),比重新 model_validate 省事。

from pydantic import BaseModel


class Item(BaseModel):
    name: str
    price: float


item = Item(name="键盘", price=199.0)
new_item = item.model_copy(update={"price": 219.0})
print(new_item.price)   # 219.0
print(item.price)       # 199.0(原对象没变)

update 传一个字典,只会覆盖你指定的字段,其余原样保留。它返回的是全新对象,不动原来的。

要注意 model_copy(update=...) 默认不会重新跑校验,传进去的值会被直接写入字段。也就是说,你若把 price 改成一个字符串,它不会像构造模型时那样报错。想让新值也经过完整校验,可以先 model_dump() 拿到字典、合并改动后再用 model_validate() 重建。另外 model_copy() 默认是浅拷贝,嵌套的子模型仍与原对象共享同一份数据,需要彻底独立时要显式传 deep=True

21-11 从 Pydantic v1 迁移的要点

如果你接手的是老项目,很可能会看到 v1 写法。对照着改,关键有这几处:把 class Config 改成 model_config = ConfigDict(...);把 orm_mode = True 改成 from_attributes=True;把 .dict() 改成 model_dump().json() 改成 model_dump_json();把 @validator 改成 @field_validator(并加 @classmethod);把 @root_validator 改成 @model_validator。官方还提供了一个 bump-pydantic 工具,能自动批量改写大部分常规代码,改完跑一遍测试即可。最新版 FastAPI 已经要求必须用 Pydantic v2,老旧的 pydantic.v1 兼容子模块也不再被新 Python 支持,所以迁移是绕不开的一步。

Note

迁移时不要混用:一个 v2 模型的字段,不能再把 v1 模型当子字段。要么全是 v2,要么分开放在两个独立模型里。

21-12 小结

本章你掌握了 Pydantic v2 的配置与序列化:model_dump() 出字典、model_dump_json() 出 JSON 串、model_validate() 从字典重建,三者是 v2 的标准三件套;model_config = ConfigDict(...) 统一管配置,其中 from_attributes=True 让你能直接从 ORM 对象加载数据,配合 model_copy 还能安全派生新对象。再次强调,所有写法都是 v2——没有 .dict()、没有 class Config、没有 orm_mode,老项目记得按本章最后一节逐条迁移。