首页
/ FastAPI 中使用 dataclasses:以标准库数据类实现请求体校验、响应序列化与自动 API 文档

FastAPI 中使用 dataclasses:以标准库数据类实现请求体校验、响应序列化与自动 API 文档

2026-09-06 11:15:33作者:胡唯隽

本篇技术指南基于 FastAPI 官方文档《Datenklassen verwenden》(使用数据类)整理并扩充,讲解如何在不写 Pydantic 模型的前提下,直接把 Python 标准库 dataclasses 用于 FastAPI 的 Request Body 参数、response_model 响应声明以及嵌套数据结构,实现与 Pydantic 模型完全一致的数据校验、序列化和 OpenAPI 文档生成能力。读完本文,你能够判断何时可以复用既有代码库中的 dataclass 定义来快速搭建 Web API,并了解其底层实现原理与能力边界。

为什么 FastAPI 能直接理解标准库 dataclasses

FastAPI 的数据处理建立在 Pydantic 之上,Pydantic 提供了对标准库 dataclasses 的内置支持。虽然下面的示例代码中完全没有显式出现 Pydantic 的导入,FastAPI 内部会自动将这些标准数据类(stdlib dataclass)转换为 Pydantic 自己的数据类变体来完成处理。

从源码结构可以印证这一机制:FastAPI 在判断"哪些参数类型应被视为复杂类型(即从 Request Body 中读取)"时,会显式检查 is_dataclass。见 fastapi/_compat/shared.py

def _annotation_is_complex(annotation: type[Any] | None) -> bool:
    return (
        lenient_issubclass(annotation, (BaseModel, Mapping, UploadFile))
        or _annotation_is_sequence(annotation)
        or is_dataclass(annotation)  # dataclass 与 Pydantic 模型并列
    )

由于数据类被归入与 BaseModel 同级的"复杂类型",FastAPI 自然获得与 Pydantic 模型相同的全部能力:

  • 数据校验(Data validation)
  • 数据序列化(Data serialization)
  • 数据文档(Data documentation,即自动生成的 OpenAPI 文档)

注意:数据类并不能做到 Pydantic 模型能做到的所有事情。在需要字段级校验器、别名、复杂的 JSON Schema 定制等能力时,你可能仍需要回到 Pydantic 模型。不过,如果现有代码库中已经散落着大量 dataclass 定义,直接复用它们是一个非常好的技巧。

用 dataclass 声明 Request Body 参数

最直接的用法是把标准库数据类直接作为路径操作函数的参数类型。示例代码位于 docs_src/dataclasses_/tutorial001_py310.py

from dataclasses import dataclass

from fastapi import FastAPI


@dataclass
class Item:
    name: str
    price: float
    description: str | None = None
    tax: float | None = None


app = FastAPI()


@app.post("/items/")
async def create_item(item: Item):
    return item

要点说明:

  • Item 是一个纯标准库 @dataclass,不继承 BaseModel,也不需要 pydantic 导入;
  • name: strprice: float 为必填字段,缺少时 FastAPI 会返回 422 校验错误;
  • descriptiontax 声明了 | None 并赋默认值 None,即为可选字段;
  • 函数参数 item: Item 被识别为 Request Body 参数,FastAPI 会校验 JSON 请求体并按 Item 的结构返回。

对应的行为验证见测试用例 tests/test_tutorial/test_dataclasses/test_tutorial001.py

在 response_model 中使用 dataclass

数据类同样可以直接作为 response_model 参数。示例代码位于 docs_src/dataclasses_/tutorial002_py310.py

from dataclasses import dataclass, field

from fastapi import FastAPI


@dataclass
class Item:
    name: str
    price: float
    tags: list[str] = field(default_factory=list)
    description: str | None = None
    tax: float | None = None


app = FastAPI()


@app.get("/items/next", response_model=Item)
async def read_next_item():
    return {
        "name": "Island In The Moon",
        "price": 12.99,
        "description": "A place to be playin' and havin' fun",
        "tags": ["breater"],
    }

关键细节:

  • 数据类会被自动转换为 Pydantic 数据类,其 JSON Schema 会出现在 Swagger UI 的 API 文档中,例如 tags 被推断为字符串数组、descriptiontax 为可空字段;
  • tags 使用了标准库惯用的 field(default_factory=list) 写法——可变默认值在数据类中必须通过 field(default_factory=...) 声明,这一点在 FastAPI 中同样适用;
  • 路径操作函数实际返回的是一个字典而非 Item 实例,FastAPI 会依据 response_model=Item 自动完成数据转换与序列化。

API 文档界面中自动生成出的数据类 Schema 如下图所示(对应文档中的截图):

FastAPI 文档界面中由 dataclass 自动生成的 Item Schema 截图

对应的请求/响应行为验证见 tests/test_tutorial/test_dataclasses/test_tutorial002.py

嵌套数据结构:结合 pydantic.dataclasses 构建复杂模型

数据类还可以与其他类型注解自由组合,形成嵌套的数据结构。在某些场景下(例如自动生成的 API 文档中出现错误时),可以换用 pydantic.dataclasses——它是标准库 dataclasses直接替代品(drop-in replacement)。示例代码位于 docs_src/dataclasses_/tutorial003_py310.py

from dataclasses import field  # (1)

from fastapi import FastAPI
from pydantic.dataclasses import dataclass  # (2)


@dataclass
class Item:
    name: str
    description: str | None = None


@dataclass
class Author:
    name: str
    items: list[Item] = field(default_factory=list)  # (3)


app = FastAPI()


@app.post("/authors/{author_id}/items/", response_model=Author)  # (4)
async def create_author_items(author_id: str, items: list[Item]):  # (5)
    return {"name": author_id, "items": items}  # (6)


@app.get("/authors/", response_model=list[Author])  # (7)
def get_authors():  # (8)
    return [  # (9)
        {
            "name": "Breaters",
            "items": [
                {
                    "name": "Island In The Moon",
                    "description": "A place to be playin' and havin' fun",
                },
                {"name": "Holy Buddies"},
            ],
        },
        {
            "name": "System of an Up",
            "items": [
                {"name": "Salt", "description": "The kombucha mushroom people's favorite"},
                {"name": "Pad Thai"},
                {
                    "name": "Lonely Night",
                    "description": "The mostests lonliest nightiest of allest",
                },
            ],
        },
    ]

按文档原文的注释编号逐条解读:

  1. field 仍然从标准库 dataclasses 导入——pydantic.dataclasses 与标准库的 field 完全兼容。
  2. pydantic.dataclassesdataclass 装饰器是标准 dataclasses 的直接替代品,只需替换导入语句。
  3. 数据类 Author 内嵌了一个 Item 数据类的列表字段,形成嵌套结构。
  4. Author 数据类被用作 response_model 参数。
  5. 可以组合其他标准类型注解与数据类作为 Request Body——这里是 list[Item]
  6. 该函数返回一个包含 items(数据类列表)的字典,FastAPI 依然能把这些数据序列化为 JSON。
  7. 此处的 response_model 使用了 list[Author] 这样的类型注解,说明数据类也能与标准容器类型组合用于响应声明。
  8. 注意这个路径操作函数使用的是普通 def 而非 async def。在 FastAPI 中二者可任意组合;关于何时用哪个的取舍,可参考文档中 async 与 await 的"赶时间?"章节
  9. 该函数返回的是字典列表而非数据类实例(虽然返回数据类也是可行的)。FastAPI 使用 response_model(其中包含数据类)来转换响应数据。

综上,你可以用多种方式把数据类与其他类型注解组合,构造出任意复杂的请求与响应数据结构。这一示例的行为验证见 tests/test_tutorial/test_dataclasses/test_tutorial003.py

能力边界与组合使用

  • 数据类 ≠ 全能替代:再次强调,数据类不能做 Pydantic 模型能做的所有事情(如高级字段配置、校验器、自定义 Schema 行为等)。复杂建模需求下,Pydantic 模型仍是首选;数据类的优势在于零改造成本地复用既有 stdlib 数据类代码
  • 与 Pydantic 模型混用:你可以把数据类与其他 Pydantic 模型组合使用,从 Pydantic 模型继承,或把数据类嵌入自有模型中,这些用法均可行。
  • 字符串化注解场景:当注解以字符串形式延迟求值时(例如 PEP 563 / from __future__ import annotations),仓库中亦有专门测试覆盖 Pydantic v2 数据类的处理,见 tests/test_pydanticv2_dataclasses_uuid_stringified_annotations.py
  • 响应序列化与校验测试:数据类参与响应序列化、响应校验的行为在 tests/test_serialize_response_dataclass.pytests/test_validate_response_dataclass.py 中有独立的用例覆盖,可作为编写类似 API 时的行为参照。

版本要求

此功能自 FastAPI 0.67.0 起可用。如果你的项目依赖更低版本,请升级后再使用数据类作为 Body 参数或 response_model

总结

FastAPI 通过 Pydantic 对标准库 dataclasses 的内置支持,让你在完全不接触 Pydantic 语法的情况下,把现有 dataclass 定义直接用作 Request Body 参数、response_model 声明或嵌套数据结构的组成部分。校验、序列化、OpenAPI 文档生成三条能力链与 Pydantic 模型完全一致,其底层归类逻辑可以在 fastapi/_compat/shared.py 中追溯。对已有大量数据类定义的代码库来说,这是一条以最小改动接入 Web API 的实用路径;而遇到建模能力不足时,用 pydantic.dataclasses 做无感替换或改回 Pydantic 模型,也是文档给出的两条标准出路。

登录后查看全文
热门项目推荐
相关项目推荐