首页
/ FastAPI 声明请求示例数据:JSON Schema examples 与 openapi_examples 的完整用法与原理

FastAPI 声明请求示例数据:JSON Schema examples 与 openapi_examples 的完整用法与原理

2026-09-06 18:49:21作者:裴锟轩Denise

如果你的 API 需要让前端、接口测试人员或下游调用方「一眼就知道该往 Body 里传什么」,那么**请求示例数据(Request Example Data)**就是最直接的沟通桥梁。本指南围绕 FastAPI 官方教程「Declare Request Example Data」(见 docs/en/docs/tutorial/schema-extra-example.md)展开,系统讲解在 Pydantic 模型、字段级 Field() 以及 Path() / Query() / Header() / Cookie() / Body() / Form() / File() 等参数工具上声明 examples 的完整方法,并深入剖析 examples 与 OpenAPI 专用 openapi_examples 两条路径的差异。读完你将能够:在自动生成的 /docs 接口文档中展示直观的单/多示例,在 OpenAPI 输出里精确控制示例的归属位置(JSON Schema 内 vs path operation 级),并理解 FastAPI 0.99.0 引入 OpenAPI 3.1.0 之后整套示例机制演进的前因后果。

三条主要声明路径一览

FastAPI 支持在三个不同层级为请求数据声明示例,它们最终都会体现到自动生成的 OpenAPI / JSON Schema 与交互式 API 文档中:

  1. Pydantic 模型层:通过模型配置 model_config["json_schema_extra"] 写入整个模型的额外 JSON Schema 数据(含 examples)。
  2. 字段层:通过 Field(examples=[...]) 为单个模型字段声明示例。
  3. 接口参数层:通过 Body() 等参数工具上的 examplesopenapi_examples 为某个路径操作声明请求数据示例。

下文将逐一演示。配套可运行源码全部位于仓库 docs_src/schema_extra_example/ 目录下,对应 tutorial001~tutorial005 的 Python 3.10 版本文件。

在 Pydantic 模型中追加 JSON Schema 额外数据(json_schema_extra)

第一种方式是在 Pydantic 模型中声明 examples,它会被原样追加到该模型生成的 JSON Schema 中,并随之进入 API 文档。核心做法是使用 Pydantic 的 model_config 属性(接受一个 dict),把任意想要出现在 JSON Schema 里的附加信息放进键 "json_schema_extra",其中自然可以包含 examples。完整示例见 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

关于该写法的几个要点:

  • 数据原样透传json_schema_extra 中的内容会被不加修改地并入 Pydantic 模型生成的 JSON Schema(Item 对应的 #/components/schemas/Item),FastAPI 生成 OpenAPI 时引用这份 Schema,文档 UI 即可读取其中的 examples
  • 不只是示例:这一技巧同样可用于扩展 JSON Schema、加入任何自定义附加信息,例如为前端界面补充元数据。json_schema_extra 的值既可以像上面一样是一个 dict,也可以是一个「入参为生成中的 schema、返回新的 schema」的 callable(由 Pydantic 负责调用)。
  • API 兼容提示:模型级 examples 之所以能正常工作,是因为 FastAPI 0.99.0 起生成的 OpenAPI 版本为 3.1.0,而 OpenAPI 3.1.0 采用的 JSON Schema 2020-12 标准本身就包含 examples 关键字(详见文末「技术细节」一节)。
  • 若遇到 Pydantic v1 项目,等价写法是把同样内容放进 class Config: json_schema_extra = {...};v2 下则统一使用 model_config。仓库内 docs_src/pydantic_v1_in_v2/ 有 Pydantic v1 语法在 v2 环境下迁移的对照示例可供参考。

用 Field() 为单个字段声明 examples

当希望按字段粒度逐个声明示例时,可以在模型字段的类型注解中使用 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

与模型级配置相比:

  • 这里每个字段的 examples(注意是列表)会进入 JSON Schema 中对应 properties 下的 examples,属于字段维度的声明,不会互相干扰。
  • examples 与字段的 default、校验规则(gtmax_length 等)完全解耦,可以分开指定,不影响校验行为。
  • 这种字段级示例在文档 UI 中会作为「该字段的推荐取值」提示呈现,适合字段含义不直观、需要给调用方「抄作业」的场景。

在接口参数工具上声明 examples(写入参数自身的 JSON Schema)

examples 同样可以用在 FastAPI 的任何参数工具上,它们分别是:

  • Path():路径参数
  • Query():查询参数
  • Header():请求头
  • Cookie():Cookie
  • Body():请求体
  • Form():表单字段
  • File():上传文件

在这些工具上声明的 examples 会被加入它们在 OpenAPI 内部的 JSON Schema。下面以 Body() 为例演示。

Body 携带单个示例

先定义一个 Item 模型,然后在接口签名中通过 Body(examples=[...]) 给出请求体应包含的数据示例。以下为基于 Annotated 的写法,见 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

FastAPI 同时支持不使用 Annotated、直接把 Body(...) 作为默认值的等价写法,见 tutorial003_py310.py。两种风格效果一致,选择其一即可(新版项目建议优先 Annotated)。

文档 UI 中的效果

采用上述任意一种方式后,访问 /docs,请求体区域会展示已声明的示例,Swagger UI 会为请求体渲染出可直接试用的样例。其界面效果如下(该图为 FastAPI 官方文档教程页截图):

FastAPI /docs 文档界面中 Body 请求示例的展示效果

Body 携带多个示例

examples 本身是列表,因此可以一次传入多个示例。见 tutorial004_an_py310.py(非 Annotated 版本见 tutorial004_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

上面三个示例刻意设计了三种形态,非常有教学价值:

  1. Foo:字段齐全的标准合法请求;
  2. Barprice 传的是字符串 "35.4",用来演示 FastAPI/Pydantic 能把字符串自动转换成数值;
  3. Bazprice 传了 "thirty five point four",这是故意给出的非法数据,用于向调用方演示「传错会收到校验错误」。

需要注意:多示例会被写入该请求体数据在 OpenAPI 内部的 JSON Schema 中。而截至教程撰写时点(文档标注 2023-08-26),负责渲染文档 UI 的 Swagger UI 尚不支持渲染 JSON Schema 内的多示例——也就是说,如果只依赖这种写法,界面上很可能看不到多个示例切换。要解决这一限制,请继续看下一节「OpenAPI 专用 examples」。

OpenAPI 专用 examples 与 openapi_examples 参数

它与 JSON Schema examples 的区别

早在 JSON Schema 引入 examples 之前,OpenAPI 就自己定义过一个同样叫 examples 的字段。这个 OpenAPI 专用 examples 的位置与上一节完全不同:它不在任何 JSON Schema 内部,而是直接挂在每个 path operation(路径操作)的细节区域。具体而言,OpenAPI 3.1 规范中:

  • Parameter Objectexamples 字段 —— 对应 FastAPI 的 Path()Query()Header()Cookie()
  • Request Body ObjectcontentMedia Type Object 上的 examples 字段 —— 对应 FastAPI 的 Body()Form()File()

它的数据形态也和 JSON Schema 版不同:是一个字典(dict)而非列表,每个 key 是一个示例名,value 是携带额外元数据的示例描述对象。Swagger UI 对这类 OpenAPI 专用 examples 支持已久,因此用它才能在文档 UI 中切换展示多个示例

openapi_examples 参数及其四个子字段

FastAPI 从 0.103.0 开始,用新参数 openapi_examples 承接上述 OpenAPI 专用 examples(此前旧文档称之为 examples,现已改名)。它适用于与上一节相同的 7 个参数工具:Path()Query()Header()Cookie()Body()Form()File()

openapi_examples 的值是一个 dict,key 用于标识每个示例,每个 value 又是另一个 dict,其中可包含以下字段:

字段 含义 说明
summary 示例的简短说明 用于在 UI 中标识该示例,例如 "A normal example"
description 长描述 支持 Markdown 文本,可对示例做详细解释
value 示例的真实数据 通常是一个 dict,即实际展示、可点击填充到请求体的内容
externalValue 示例的外部 URL value 的替代方案,指向存放示例内容的链接;不过支持它的工具没有 value 那么普遍

用法示例

以下代码在 Body() 上声明了三个带「场景化说明」的 OpenAPI 专用示例,见 tutorial005_an_py310.py(非 Annotated 版本见 tutorial005_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

三个示例分别对应「正常请求」「字符串价格被自动转换」「非法数据被校验拦截」,配合 summary 与支持 Markdown 的 description,能把每种请求的语义讲解得非常清楚,非常适合用于团队协作与对外 API 文档。

OpenAPI 示例在文档 UI 中的效果

Body() 添加 openapi_examples 后,/docs 页面会以可切换示例的方式渲染请求体,用户可点击不同示例名并一键填充到请求内容。效果如下:

FastAPI /docs 文档界面中基于 openapi_examples 的多示例切换展示

源码印证:examples 如何被写进 OpenAPI

上述声明最终都会在生成 OpenAPI 时被落地。可以在本仓库 fastapi/openapi/utils.py 中看到精确的实现逻辑:

路径/查询/请求头/Cookie 参数(对应 Path/Query/Header/Cookie)位于 get_openapi_path 构造 parameters 的过程里,fastapi/openapi/utils.py

openapi_examples = getattr(field_info, "openapi_examples", None)
example = getattr(field_info, "example", None)
if openapi_examples:
    parameter["examples"] = jsonable_encoder(openapi_examples)
elif example is not _Unset:
    parameter["example"] = jsonable_encoder(example)

请求体(对应 Body/Form/File)则在 get_openapi_operation_request_body 中,把示例放进 content 下媒体类型的映射里,fastapi/openapi/utils.py

request_media_content: dict[str, Any] = {"schema": body_schema}
if field_info.openapi_examples:
    request_media_content["examples"] = jsonable_encoder(
        field_info.openapi_examples
    )
elif field_info.example is not _Unset:
    request_media_content["example"] = jsonable_encoder(field_info.example)

两点可以注意:

  1. 优先级明确openapi_examples 存在时优先写入(落到 examples);否则回退到旧的单一 example 字段。这从代码层面印证了官方「推荐用 examples 替代旧的 example」的取向。
  2. 参数定义源头openapi_examplesjson_schema_extra 参数在 Path/Query/Header/Cookie/Body/Form/File 各自的构造函数中均有声明(可参考 fastapi/param_functions.pyopenapi_examplesjson_schema_extra 的出现位置),与上文列出的 7 个工具一一对应。

模型级声明走的是另一条链路:Pydantic 依据 model_config["json_schema_extra"]Field(examples=...) 生成模型 JSON Schema(仓库兼容层 fastapi/_compat/v2.py 中可见 "json_schema_extra": None 之类的默认配置项),FastAPI 再把模型 Schema 嵌入 OpenAPI 的 components/schemas,文档 UI 读取后渲染。仓库中的 tests/test_schema_extra_examples.py 等测试对这两种 examples 的输出结果均有断言,可作为改动后回归验证的入口。

技术细节:JSON Schema 与 OpenAPI 的示例演进史

如果你正在使用 FastAPI 0.99.0 及以上版本,前面几节的内容已经足够,本节属于「历史课」,主要面向老版本用户或想彻底理解标准差异的读者。

OpenAPI 3.1.0 之前:各自为政的 example

在 OpenAPI 3.1.0 出现之前,OpenAPI 使用的是旧版且经过修改的 JSON Schema。当时 JSON Schema 还没有 examples,因此 OpenAPI 在自己的改造版中补了一个 example 字段;此外 OpenAPI 还在规范的其他部位自行添加了 example / examples

  • Parameter Object 上的示例字段 —— 对应 FastAPI 的 Path()Query()Header()Cookie()
  • Request Body ObjectcontentMedia Type Object 上的示例字段 —— 对应 FastAPI 的 Body()File()Form()

这就是两套同名词条长期并存的根源。

JSON Schema 的 examples 与 OpenAPI 3.1.0

随后 JSON Schema 在自己的新版本规范(自 draft 2019-09 起引入)中增加了 examples 字段,而基于 JSON Schema 2020-12 的全新 OpenAPI 3.1.0 因此天然继承了该字段。在新规范下,JSON Schema 内的 examples 只是一个示例值的列表list),没有额外的元数据字典包装。

examples 与旧 example 同时存在时,新的 examples 拥有更高优先级,旧的单值 example 字段虽仍被 OpenAPI 3.1.0 支持,但已标记为弃用且不属于 JSON Schema 标准,官方鼓励将 example 迁移为 examples

FastAPI 各版本与此的对应关系

  • OpenAPI 3.1.0 正式发布后的一段时间里,Swagger UI 并不支持 OpenAPI 3.1.0(直到 Swagger UI 5.0.0 起才支持)。因此 FastAPI 0.99.0 之前的版本仍输出低于 3.1.0 的 OpenAPI。
  • FastAPI 0.99.0 起改用更新的 OpenAPI 3.1.0(即 JSON Schema 2020-12),配合 Swagger UI 5.0.0+,examples 得以统一收录进 JSON Schema,整条链路更加一致。
  • Swagger UI 仍不渲染 JSON Schema 内的多个示例(截至 2023-08-26),为了在文档中展示多个示例,FastAPI 0.103.0 新增了 openapi_examples 参数,用来声明那组挂在 path operation / media type 层级的 OpenAPI 专用 examples

演进前后示例落点的差异

  • 旧版本中,用 Query()Body() 等工具声明 example / examples 时,内容不会进入描述该数据的 JSON Schema(甚至也不在 OpenAPI 自己的 JSON Schema 版本里),而是直接写入 OpenAPI 中该 path operation 的声明区域(即所有使用 JSON Schema 的区块之外)。
  • 新版本(FastAPI 0.99.0+)中,一切趋于一致:Pydantic 模型内的 examples 进入模型 JSON Schema;Body() 等工具上的 JSON Schema examples 进入参数对应的 schema;openapi_examples 则保留在 OpenAPI 操作级区域供 UI 做多示例切换。

实践建议与小结

场景 推荐做法
想让整个模型在文档中展示推荐请求体 模型上配置 model_config["json_schema_extra"]["examples"]
想按字段逐一给出示例取值 字段使用 Field(examples=[...])
只想给某个接口的请求体/参数配一个示例 参数工具(Body() 等)上传 examples=[{...}]
想在文档 UI 中切换展示多个示例并附说明 参数工具上传 openapi_examples={...},配合 summary / description / value

总的原则是:升级到 FastAPI 0.99.0 及以上examples 的语义在各层保持一致且直观;若需要在 Swagger UI 中展示多示例,再使用 0.103.0+ 引入的 openapi_examples。示例声明只影响文档与 Schema 输出,不改变任何校验行为,因此可以放心为「正常请求」「边界数据」乃至「故意非法」的场景各配一份,帮助 API 使用方把请求一次写对。

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

项目优选

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