首页
/ FastAPI 声明请求示例数据全指南:model_config、Field(examples) 与 openapi_examples

FastAPI 声明请求示例数据全指南:model_config、Field(examples) 与 openapi_examples

2026-09-07 11:12:56作者:韦蓉瑛

本篇技术指南以 docs/fr/docs/tutorial/schema-extra-example.md(英文原文见 docs/en/docs/tutorial/schema-extra-example.md)为核心脉络,系统讲解如何在 FastAPI 中为接口声明“请求示例数据”:既可以在 Pydantic 模型层通过 model_config / Field() 让示例进入 JSON Schema,也可以通过 Path()Query()Body() 等参数工具直接携带示例;并深入剖析 examples(JSON Schema 级)与 openapi_examples(OpenAPI 级)这两套字段的区别、演进历史及在 /docs 交互文档中的实际效果。读完本文,你将能根据需求为任意路径操作或数据模型配置"可复制、可演示、多版本可切换"的请求示例。

所有演示代码均取自仓库中的 docs_src/schema_extra_example/ 目录(Python 3.10+ 语法版本,文件后缀 _py310),并配套说明底层实现依据,可直接运行验证。

总览:声明示例数据的三种入口

FastAPI 中“声明请求示例数据”可以归结为三种方式,对应不同的生成产物与作用范围:

  1. 模型级:在 Pydantic 模型的 model_config 中设置 "json_schema_extra",或在 Field() 中传入 examples=[...],数据会原样进入该模型产出的 JSON Schema
  2. 参数级(JSON Schema 内):在使用 Path()Query()Header()Cookie()Body()Form()File() 时传入 examples=[...],示例进入这些参数的 JSON Schema 并随 OpenAPI 输出;
  3. 参数级(OpenAPI 路径操作级):同样在上述七种参数工具上使用 openapi_examples={...},示例被写入 OpenAPI 规范中 每个路径操作(path operation)examples 字段,从而让 Swagger UI 提供多个示例的下拉切换

下文先讲模型级与参数级的基础用法,再深入 openapi_examples 与标准演进的技术细节。

在 Pydantic 模型中用 model_config 扩展 JSON Schema

你可以为 Pydantic 模型声明 examples,它们会被添加到生成的 JSON Schema 中。完整示例见 tutorial001_py310.py

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


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

    model_config = {
        "json_schema_extra": {
            "examples": [
                {
                    "name": "Foo",
                    "description": "A very nice Item",
                    "price": 35.4,
                    "tax": 3.2,
                }
            ]
        }
    }


@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
    results = {"item_id": item_id, "item": item}
    return results

要点如下:

  • 这些额外信息会被**原样(as-is)**加入该模型输出的 JSON Schema,并最终用于 API 文档(/docs)展示;
  • model_config 是 Pydantic v2 的类级配置属性,接受一个 dict;其中的 "json_schema_extra" 键可以放入任意你希望出现在生成 JSON Schema 中的数据,examples 只是最常见的一种;
  • 这种手法同样适用于扩展 JSON Schema 加入自定义元数据,例如为前端用户界面补充标记信息等,不局限于示例数据。

注意:OpenAPI 3.1.0(自 FastAPI 0.99.0 起使用)原生支持 examples,它是 JSON Schema 标准的一部分。在此之前的版本只支持单值关键字 example。OpenAPI 3.1.0 仍然兼容 example,但它已被标记为弃用,且不属于 JSON Schema 标准,因此官方建议将 example 迁移到 examples

使用 Field() 的额外参数声明字段级示例

当使用 Pydantic 的 Field() 时,也可以在每个字段上声明自己的 examples,见 tutorial002_py310.py

from fastapi import FastAPI
from pydantic import BaseModel, Field

app = FastAPI()


class Item(BaseModel):
    name: str = Field(examples=["Foo"])
    description: str | None = Field(default=None, examples=["A very nice Item"])
    price: float = Field(examples=[35.4])
    tax: float | None = Field(default=None, examples=[3.2])


@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
    results = {"item_id": item_id, "item": item}
    return results

与模型级方式相比,Field(examples=[...]) 把示例细分到了字段维度:每个字段可独立给出"该字段看起来像什么",最终同样合并到模型对应的 JSON Schema 中。注意 examples 参数是一个 list,即使只有一个示例也要写成列表形式。

在七种参数工具上声明 JSON Schema 级 examples

除了模型内部,使用以下任一 FastAPI 参数工具时,也可以声明一组 examples,它们会被加入 OpenAPI 内部对应参数的 JSON Schema

  • Path()
  • Query()
  • Header()
  • Cookie()
  • Body()
  • Form()
  • File()

Body() 携带单个 examples

以请求体为例,给 Body() 传入包含期望数据的 examples,见 tutorial003_an_py310.py

from typing import Annotated

from fastapi import Body, FastAPI
from pydantic import BaseModel

app = FastAPI()


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


@app.put("/items/{item_id}")
async def update_item(
    item_id: int,
    item: Annotated[
        Item,
        Body(
            examples=[
                {
                    "name": "Foo",
                    "description": "A very nice Item",
                    "price": 35.4,
                    "tax": 3.2,
                }
            ],
        ),
    ],
):
    results = {"item_id": item_id, "item": item}
    return results

使用 Annotated[...]Body(...) 的元数据绑定到参数上是目前推荐的写法。采用上述任意方式后,/docs 界面中的请求体会展示该示例值,效果见下图:

FastAPI /docs 中单个 JSON Schema 示例的展示效果(Example Value)

Body() 携带多个 examples

自然也可以传入多个示例,见 tutorial004_an_py310.py

from typing import Annotated

from fastapi import Body, FastAPI
from pydantic import BaseModel

app = FastAPI()


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


@app.put("/items/{item_id}")
async def update_item(
    *,
    item_id: int,
    item: Annotated[
        Item,
        Body(
            examples=[
                {
                    "name": "Foo",
                    "description": "A very nice Item",
                    "price": 35.4,
                    "tax": 3.2,
                },
                {
                    "name": "Bar",
                    "price": "35.4",
                },
                {
                    "name": "Baz",
                    "price": "thirty five point four",
                },
            ],
        ),
    ],
):
    results = {"item_id": item_id, "item": item}
    return results

这里的多个示例会被并入该请求体数据内部的 JSON Schema(注意示例本身并不代表数据一定合法,例如上例中的 "price": "thirty five point four" 是故意用来演示非法数据的)。需要特别说明的是:截至本文写作时(原文记录为 2023-08-26),负责渲染文档界面的 Swagger UI 尚不支持在 JSON Schema 层面展示多个示例——它只会显示其中一个。解决这个限制的方法,就是下面介绍的 OpenAPI 特有的 openapi_examples

openapi_examples 声明 OpenAPI 级多示例

JSON Schema 支持 examples 之前,OpenAPI 规范就已经拥有一个同样名为 examples、但语义不同的字段。

这个 OpenAPI 特有的 examples 位于规范的另一处:它挂在每个路径操作(path operation)的细节里,而不是嵌在每个 JSON Schema 内部。由于 Swagger UI 早已支持该字段,因此可以用它来在文档界面中展示并切换多个示例

它的数据结构是一个 dict(而不是 list):外层 标识每个示例, 是另一个 dict,其中的可选字段如下:

  • summary:示例的简短描述;
  • description:较长的描述,可包含 Markdown 文本;
  • value:实际展示的示例数据,例如一个 dict
  • externalValuevalue 的替代项,是一个指向示例内容的 URL;不过它可能不如 value 那样被众多工具支持。

FastAPI 中通过参数 openapi_examples 声明它,可用于:Path()Query()Header()Cookie()Body()Form()File()。完整示例见 tutorial005_an_py310.py

from typing import Annotated

from fastapi import Body, FastAPI
from pydantic import BaseModel

app = FastAPI()


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


@app.put("/items/{item_id}")
async def update_item(
    *,
    item_id: int,
    item: Annotated[
        Item,
        Body(
            openapi_examples={
                "normal": {
                    "summary": "A normal example",
                    "description": "A **normal** item works correctly.",
                    "value": {
                        "name": "Foo",
                        "description": "A very nice Item",
                        "price": 35.4,
                        "tax": 3.2,
                    },
                },
                "converted": {
                    "summary": "An example with converted data",
                    "description": "FastAPI can convert price `strings` to actual `numbers` automatically",
                    "value": {
                        "name": "Bar",
                        "price": "35.4",
                    },
                },
                "invalid": {
                    "summary": "Invalid data is rejected with an error",
                    "value": {
                        "name": "Baz",
                        "price": "thirty five point four",
                    },
                },
            },
        ),
    ],
):
    results = {"item_id": item_id, "item": item}
    return results

Body() 添加 openapi_examples 后,/docs 界面会渲染出可切换的多示例下拉框(示例名称取自外层键,展示内容取自各值中的 summary / description / value):

FastAPI /docs 中 openapi_examples 提供的多示例下拉切换效果

底层实现依据

在仓库源码中可以看到这套设计的直接实现:

  • fastapi/param_functions.py 中,Path/Query/Header/Cookie/Body/Form/File 等函数均接受参数 examples: list[Any] | Noneopenapi_examples: dict[str, Example] | None;同时 example: Any 参数被标记为 deprecated,其弃用说明为 "Deprecated in OpenAPI 3.1.0 that now uses JSON Schema 2020-12, although still supported. Use examples instead."(见该文件中每个参数工具的注解区块);
  • fastapi/openapi/utils.py 生成 OpenAPI 时:对于查询/路径等参数,openapi_examples 会写入参数对象顶层的 parameter["examples"]第 219-224 行);对于请求体,则写入 request_media_content["examples"]第 256-261 行),并优先于旧的 example 字段——这正是“OpenAPI 特有示例位于 JSON Schema 之外”的实现落点;
  • 对应的行为测试集中在 tests/test_openapi_examples.py 中,可据此验证上述输出结构。

技术细节:一段 OpenAPI 与 JSON Schema 的演进历史

如果你已经在使用 FastAPI 0.99.0 及以上版本,以下内容可以跳过——它主要面向旧版本(尚未引入 OpenAPI 3.1.0 之前)的兼容问题,可看作一段简短的 OpenAPI / JSON Schema 历史课,有助于你理解为什么当前 API 中会同时存在 examplesopenapi_examples 两种写法。

警告:以下是关于 JSON SchemaOpenAPI 标准的高度技术性细节。如果上面的用法已经满足需求,可以放心跳过本节。

演进起点:OpenAPI 自带的 example

在 OpenAPI 3.1.0 之前,OpenAPI 使用的是较旧且被修改过的 JSON Schema 版本。当时的 JSON Schema 并没有 examples,于是 OpenAPI 在其修改版中自行加入了 example 字段。此外,OpenAPI 还在规范的其他位置补加了 exampleexamples 字段:

  • Parameter Object:对应 FastAPI 的 Path()Query()Header()Cookie()
  • Request Body Object 中 content 字段下的 Media Type Object:对应 FastAPI 的 Body()File()Form()

注意:这个旧版 OpenAPI 特有的 examples 参数,自 FastAPI 0.103.0 起被重命名为 openapi_examples

JSON Schema 的 examples 字段

随后,JSON Schema 在新版规范(2019-09 draft 起引入校验关键字)中增加了 examples 字段;再后来,全新的 OpenAPI 3.1.0 基于包含该字段的最新版 JSON Schema 2020-12 构建。新的 examples 字段由此取代了旧的单值自定义字段 example,后者现在处于弃用状态。

注意一个容易混淆的差异:JSON Schema 中的 examples 仅仅是一个 list(一列示例值),并不是像 OpenAPI 其他位置那样带 summary/description 元数据的 dict

补充:即便 OpenAPI 3.1.0 发布并带来了与 JSON Schema 更简洁的整合,负责渲染自动文档的 Swagger UI 在一段时间内仍不支持 OpenAPI 3.1.0(直到 Swagger UI 5.0.0 起才支持)。正因如此,FastAPI 0.99.0 之前的版本一直使用低于 3.1.0 的 OpenAPI 版本。

不同写法在 Pydantic / FastAPI 中的归宿

  • 在 Pydantic 模型内通过 schema_extra(或 v2 的 json_schema_extra)或 Field(examples=[...]) 添加的 examples,会被写入该 Pydantic 模型的 JSON Schema;这个模型 JSON Schema 又会被嵌入 API 的 OpenAPI 文档,并在文档界面中使用。
  • 在 FastAPI 0.99.0 之前的版本中,通过 Query()Body() 等参数工具使用 exampleexamples 时,示例不会被加入描述该数据的 JSON Schema(甚至不属于 OpenAPI 自己的 JSON Schema 变体),而是被直接写入 OpenAPI 中路径操作的声明处(即所有使用 JSON Schema 的区域之外)。
  • 从 FastAPI 0.99.0 起改用 OpenAPI 3.1.0(基于 JSON Schema 2020-12),加上 Swagger UI 5.0.0+ 的配合,整体趋于一致:示例被纳入 JSON Schema 之中。

为什么还需要 openapi_examples

尽管现代 FastAPI 已把参数级 examples 并入 JSON Schema,但 Swagger UI 截至 2023-08-26 仍不支持在文档界面展示“JSON Schema 中的多个示例”,因此用户缺少一条展示多示例的途径。为解决这一缺口,FastAPI 0.103.0 新增了 openapi_examples 参数,用于声明同一份旧版 OpenAPI 特有examples 字段——这正是上文第 4 节内容存在的根本原因。在 fastapi/params.py 中可以看到,参数基类 Param 构造器接收 openapi_examples: dict[str, Example] | None 并保存在 self.openapi_examples,随后由 OpenAPI 生成逻辑按"路径操作级"字段输出。

小结

归根结底,官方给出的最简结论是:升级到 FastAPI 0.99.0 或更高版本,配合较新的 Swagger UI,示例数据的处理会更加简单、一致、直观,大部分历史细节你都不必再关心;此时只需按用途选择:

  • 想让示例进入模型/字段的 JSON Schema,用 model_config["json_schema_extra"]Field(examples=[...])
  • 想让单个示例进入具体参数的 JSON Schema,在 Body() 等参数工具上传 examples=[...]
  • 想获得多示例下拉切换的文档体验,使用参数工具上的 openapi_examples={...}

另外提醒:当前仓库示例代码以 Annotated 结合 Python 3.10+ 类型语法编写(str | None),运行前请确认解释器版本满足要求,相关可直接运行的源码均可在 docs_src/schema_extra_example/ 目录中找到,对应的行为断言可参考 tests/test_openapi_examples.py

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

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391