跳转至

声明请求的示例数据

FastAPI 支持为应用中的数据声明示例。

以下是几种实现的方式。

Pydantic 的 schema_extra

使用 Configschema_extra 为 Pydantic 模型声明 example, 详见 Pydantic 文档:自定义概图

from typing import Union

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: Union[str, None] = None
    price: float
    tax: Union[float, None] = None

    class Config:
        schema_extra = {
            "example": {
                "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
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

    class Config:
        schema_extra = {
            "example": {
                "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 中会为模型添加这些附加信息,并显示在 API 文档中。

提示

同样,可以扩展 JSON Schema,并添加更多自定义信息。

例如,为前端用户界面添加元数据等信息。

更多 Field 参数

向 Pydantic 模型的 Field() 传递参数,可以为 JSON Schema 声明更多信息。

使用 Field() 为字段添加 example

from typing import Union

from fastapi import FastAPI
from pydantic import BaseModel, Field

app = FastAPI()


class Item(BaseModel):
    name: str = Field(example="Foo")
    description: Union[str, None] = Field(default=None, example="A very nice Item")
    price: float = Field(example=35.4)
    tax: Union[float, None] = Field(default=None, example=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
from fastapi import FastAPI
from pydantic import BaseModel, Field

app = FastAPI()


class Item(BaseModel):
    name: str = Field(example="Foo")
    description: str | None = Field(default=None, example="A very nice Item")
    price: float = Field(example=35.4)
    tax: float | None = Field(default=None, example=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

警告

注意,传递的这些参数不添加验证,只添加供文档使用的额外信息。

OpenAPI 中的 exampleexamples

使用以下函数时:

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

还可以通过声明数据的 example,或一组 examplesOpenAPI 添加更多信息。

Body 中使用 example

下列代码向 Body() 传递example 数据:

from typing import Union

from fastapi import Body, FastAPI
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: Union[str, None] = None
    price: float
    tax: Union[float, None] = None


@app.put("/items/{item_id}")
async def update_item(
    item_id: int,
    item: Item = Body(
        example={
            "name": "Foo",
            "description": "A very nice Item",
            "price": 35.4,
            "tax": 3.2,
        },
    ),
):
    results = {"item_id": item_id, "item": item}
    return results
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: Item = Body(
        example={
            "name": "Foo",
            "description": "A very nice Item",
            "price": 35.4,
            "tax": 3.2,
        },
    ),
):
    results = {"item_id": item_id, "item": item}
    return results

文档中的示例

上述示例代码在文档 /docs 中的显示效果如下:

Body 中使用 examples

除了单个的 example,还可以使用 dict 传递 examples,以此来显示多个示例,这些示例信息也会被添加至 OpenAPI

dict 通过识别示例,这些示例的值也是 dict

examplesdict 包含下列内容:

  • summary:示例简述。
  • description:支持 Markdown 格式的较长描述。
  • value:实际显示的示例,可以是字典
  • externalValuevalue 的备选项,指向示例的 URL,但可能有些工具不支持。
from typing import Union

from fastapi import Body, FastAPI
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    description: Union[str, None] = None
    price: float
    tax: Union[float, None] = None


@app.put("/items/{item_id}")
async def update_item(
    *,
    item_id: int,
    item: Item = Body(
        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
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: Item = Body(
        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() 中包含 examples 时,在文档 /docs 中的显示如下图:

技术细节

警告

JSON SchemaOpenAPI 相关的技术细节很多。

一般情况下,理解上文中的代码就已经够用了,下面的技术细节不是必须的,跳过阅读也无所谓。

在 Pydantic 模型内部添加示例时, 使用 schema_extraField(example="something") ,就可以把 Pydantic 模型的示例添加至 JSON Schema

Pydantic 模型的 JSON Schema 包含在 API 的 OpenAPI 中,并在文档中显示。

实际上,JSON Schema 标准中没有 example。新版 JSON Schema 中定义了 examples 字段,但 OpenAPI 3.0.3 基于的旧版 JSON Schema 没有examples 字段。

因此,OpenAPI 3.0.3 定义了自己的 example,供新版 JSON Schema 使用(但它用的只是 example,不是 examples)。同样,(使用 Swagger UI 的)API 文档中用的也是 example

example 不是 JSON Schema 的组件,但它是 OpenAPI 为 JSON Schema 定制的组件,因此,文档中使用 example

但在(Query()Body() 等)其他工具中使用 exampleexamples 时,这些描述数据的示例不会被添加至 JSON Schema(包括 OpenAPI 自己的 JSON Schema),而是被直接添加至 OpenAPI 的路径操作声明里(OpenAPI 使用 JSON Schema 外部的组件)。

对于 Path()Query()Header()Cookie()exampleexamples 被添加至 OpenAPI 定义中的Parameter Object(规范)

对于 Body()File()Form()exampleexamples 被添加至 OpenAPI 定义中content 字段里的 Request Body Object 中的 Media Type Object(规范)

另一方面,新近发布的 OpenAPI 3.1.0 版已经支持最新的 JSON Schema, 移除了绝大多数 OpenAPI 自定义的 JSON Schema,从而可以使用新版 JSON Schema 的功能,它们之间的细微区别也进一步减少。但 Swagger UI 现在还不支持 OpenAPI 3.1.0,因此,现在最好还是使用本章中的开发思路。