FastAPI 宣告 API UI 文件範例資料 (API Doc Schema Examples)

在開發 API 時,提供清晰的範例資料對於前端開發者來說非常重要。FastAPI 允許你在定義 Pydantic Model 時,直接宣告該 Model 的範例資料。

這些範例資料會直接顯示在 Swagger UI (/docs) 和 ReDoc (/redoc) 中,讓使用者可以一鍵填入範例進行測試。

方法一:使用 model_config (Pydantic v2 推薦)

如果你使用的是最新版的 Pydantic v2 (FastAPI 0.100+ 預設搭配),這是最推薦的寫法。使用 model_config 屬性並設定 json_schema_extra

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):
    return {"item_id": item_id, "item": item}
如果你安裝的 fastapipydantic 都是最新版,通常已經預設使用 Pydantic v2。但為了確保相容性,FastAPI 對舊寫法也有很好的支援。目前大多數教學仍以 Pydantic v1 的寫法 (Config 類別) 為主,因為它在許多專案中仍被廣泛使用。

方法二:使用 Field (個別欄位級別)

你也可以針對個別欄位使用 Fieldexamples (Pydantic v2) 參數。

from typing import Annotated
from pydantic import BaseModel, Field

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

Body 參數的範例資料

如果你不想修改 Pydantic Model (例如該 Model 是共用的),你也可以在 Body 中直接宣告範例。

from fastapi import Body

@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

多個範例 (Multiple Examples)

在 OpenAPI 3.10+ (FastAPI 支援),你可以提供多個不同的範例供使用者選擇。

@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/Pydantic converts valid data automatically.",
                "value": {
                    "name": "Bar",
                    "price": "35.4", # String will be converted to float
                },
            },
            "invalid": {
                "summary": "Invalid data is rejected with an error",
                "value": {
                    "name": "Baz",
                    "price": "thirty five point four", # Invalid float
                },
            },
        },
    ),
):
    results = {"item_id": item_id, "item": item}
    return results

在 Swagger UI 中,使用者會有一個下拉式選單可以切換這些範例。

總結

為 API 添加範例資料是提升開發者體驗 (DX) 的重要一環。 你可以選擇:

  1. Pydantic Model 中定義 (Configmodel_config) -> 全域適用
  2. Field 中定義 -> 欄位級別
  3. Body 參數中定義 -> 特定路由適用