本文 AI 產出,尚未審核

FastAPI 教學:自訂 OpenAPI Example(Swagger / ReDoc)

簡介

在使用 FastAPI 建立 API 時,除了撰寫正確的路由與邏輯外,文件化 也是不可或缺的工作。FastAPI 內建支援 OpenAPI(即 Swagger / ReDoc),會自動根據型別註解產生互動式文件,讓前端、測試或第三方開發者可以直接「點選」測試 API。

然而,預設產生的範例(example)往往過於簡單或不符合實務需求,導致文件看起來不具說服力,甚至讓使用者誤解欄位格式。自訂 Example 能讓文件更貼近真實資料、提升可讀性與測試效率,對於開發團隊與 API 消費者都非常重要。本文將一步步說明如何在 FastAPI 中設定自訂 Example,並提供多個實用範例、常見陷阱與最佳實踐,幫助你打造高品質的 API 文件。


核心概念

1. 為什麼需要自訂 Example?

  • 提升可讀性:清楚示範欄位的資料型別與格式(如日期、enum、嵌套物件)。
  • 加速開發測試:使用 Swagger UI 點擊「Try it out」時,預設值即為我們想要的測試資料。
  • 降低錯誤率:讓 API 使用者不必自行猜測或查找說明文件,即可直接取得正確範例。

2. OpenAPI 中的 exampleexamples

  • example:單一範例值,適用於簡單欄位或整體回傳模型。
  • examples:可提供多組範例,常用於說明不同情境(如成功 vs 錯誤)。

FastAPI 透過 Pydantic 的模型定義與 Path/Query/Body 參數的 example 參數,將這些資訊寫入 OpenAPI 文件。

3. 設定位置

自訂 Example 可以放在以下幾個層級:

層級 使用方式 典型情境
Path / Query / Header Path(..., example="123")Query(..., example=10) 單一參數的範例
Request Body(Pydantic Model) 在欄位 Field(..., example=…) 或模型 Config.schema_extra 複雜物件、嵌套結構
Response Model response_model=MyModel + example / examplesResponse 回傳資料的範例
全局 OpenAPI app.openapi_schema["components"]["schemas"] 手動編輯 需要一次性覆寫多個模型

程式碼範例

以下示範 5 個常見且實用的自訂 Example 實作方式。程式碼均以 Python(FastAPI)撰寫,使用 python 語法標記。

1️⃣ 基本 Path / Query 參數的 Example

from fastapi import FastAPI, Path, Query

app = FastAPI(title="自訂 Example 示範")

@app.get("/items/{item_id}")
def read_item(
    item_id: int = Path(..., title="商品編號", example=42),
    q: str | None = Query(None, title="搜尋關鍵字", example="fastapi")
):
    """
    取得單一商品資訊。  
    - **item_id**: 商品編號,範例 42  
    - **q**: 可選的搜尋關鍵字,範例 "fastapi"
    """
    return {"item_id": item_id, "q": q}

重點Path(..., example=42) 直接把 42 放入 Swagger UI 的預設值,使用者只要點「Try it out」就會看到。

2️⃣ 使用 Field 為 Pydantic 欄位設定 Example

from pydantic import BaseModel, Field

class UserCreate(BaseModel):
    username: str = Field(..., min_length=3, max_length=20, example="alice")
    password: str = Field(..., min_length=6, example="s3cr3t!")
    email: str | None = Field(None, example="alice@example.com")
@app.post("/users", response_model=UserCreate)
def create_user(user: UserCreate):
    """
    建立新使用者,Swagger UI 會自動帶入上述 Example。
    """
    # 這裡省略實作,只回傳收到的資料
    return user

說明Field(..., example=…) 能為每個欄位提供獨立範例,對於 必填可選 欄位皆適用。

3️⃣ 在模型層級一次設定多筆 Example(schema_extra

class Product(BaseModel):
    id: int = Field(..., example=1)
    name: str = Field(..., example="Smartphone")
    price: float = Field(..., gt=0, example=299.99)
    tags: list[str] = Field(default_factory=list, example=["electronics", "mobile"])

    class Config:
        schema_extra = {
            "example": {
                "id": 101,
                "name": "Wireless Earbuds",
                "price": 79.5,
                "tags": ["audio", "bluetooth"]
            }
        }
@app.get("/products/{product_id}", response_model=Product)
def get_product(product_id: int = Path(..., example=101)):
    # 假設從資料庫撈資料,這裡直接回傳範例
    return Product(**Product.Config.schema_extra["example"])

技巧schema_extra["example"] 為模型層級的 單一 範例,適合在 回傳模型 中一次設定全部欄位。

4️⃣ 多組回傳範例(examples)與 HTTP 狀態碼

from fastapi.responses import JSONResponse

@app.get(
    "/status/{code}",
    responses={
        200: {
            "description": "成功回傳",
            "content": {
                "application/json": {
                    "example": {"message": "All good!"}
                }
            },
        },
        400: {
            "description": "錯誤範例",
            "content": {
                "application/json": {
                    "examples": {
                        "missing": {
                            "summary": "缺少參數",
                            "value": {"detail": "Missing required query parameter"}
                        },
                        "invalid": {
                            "summary": "參數格式錯誤",
                            "value": {"detail": "Invalid value for parameter"}
                        },
                    }
                }
            },
        },
    },
)
def get_status(code: int = Path(..., example=200)):
    if code == 200:
        return JSONResponse(content={"message": "All good!"})
    return JSONResponse(status_code=400, content={"detail": "Invalid request"})

說明:在 responses 中使用 examples 可以一次提供多個錯誤回傳範例,Swagger UI 會在「Responses」區塊顯示所有情境,對測試非常友善。

5️⃣ 針對 ReDoc 顯示自訂 Example(使用 exampleexamples

class Order(BaseModel):
    order_id: str = Field(..., example="ORD-20231120-001")
    amount: float = Field(..., gt=0, example=1500.75)
    status: str = Field(..., example="pending")
    items: list[dict] = Field(
        ...,
        example=[
            {"product_id": 101, "quantity": 2},
            {"product_id": 205, "quantity": 1},
        ],
    )
@app.post("/orders", response_model=Order, status_code=201)
def create_order(order: Order):
    """
    建立訂單。ReDoc 會顯示完整的 JSON 範例,讓使用者一目了然。
    """
    # 這裡僅回傳收到的資料
    return order

要點:ReDoc 預設會顯示模型的 example(若有),若想要多組範例,可在 OpenAPI components 手動加入 examples,不過對大多數情況而言,單一 example 已足夠。


常見陷阱與最佳實踐

陷阱 說明 解決方案 / Best Practice
範例與實際驗證不一致 只在 example 裡寫假資料,卻忘了在 Field 加上 regexgt 等驗證,導致文件看起來正確但實際請求失敗。 同時使用 example + 欄位驗證,確保範例符合模型限制。
忘記在 Path / Queryexample Swagger UI 只會顯示空白欄位,使用者必須自行輸入,降低體驗。 統一規範:所有公開的參數皆必須提供 example(即使是 None 也可寫 example=None)。
過度冗長的 schema_extra 把太多不必要的資料寫進 example,導致文件過大、載入緩慢。 只保留 關鍵欄位,其他欄位可省略或使用 ... 表示省略。
多組 examples 與 UI 不相容 某些舊版 Swagger UI 只支援單一 example,會忽略 examples 若需兼容舊版,提供 單一 example 並在說明文字中列出其他情境。
範例包含敏感資訊 把真實 API 金鑰、密碼寫進 example,會在文件中公開。 使用 虛擬資料(如 ***<your-token>),永遠不要寫入真實憑證。

推薦的寫作風格

  1. 一致性:所有模型與參數的 example 都以相同的資料格式呈現(如日期使用 ISO 8601)。
  2. 可讀性:在 example 中加入易懂的值(如 "alice"42),避免使用過於抽象的代碼。
  3. 分層說明:在模型說明文字(docstring)中補充 為什麼 需要這個欄位,讓文件更具教育意義。
  4. 版本管理:若 API 需變更範例,請同步更新 example 與驗證規則,避免文件不同步。

實際應用場景

場景 為何需要自訂 Example 實作概觀
前端開發者測試 UI 前端需要快速知道 API 需要什麼樣的 JSON 結構。 UserCreate 模型使用 Field(..., example=…),讓 Swagger UI 直接生成測試資料。
第三方合作夥伴整合 合作夥伴常透過 Postman 匯入 OpenAPI,範例決定他們的測試腳本。 使用 responses 中的 examples 提供成功與錯誤的完整回傳範例。
自動化測試 (CI) 測試腳本會根據 OpenAPI 產生測試資料。 在模型 Config.schema_extra 定義完整範例,測試框架自動抓取。
API 文件外部發布 客戶或業務人員需要一份易讀的 API 手冊。 透過 ReDoc 部署,範例會直接呈現在文件中,提高說服力。
多語系或多環境 同一 API 在測試環境與正式環境的回傳結構略有差異。 使用 example 結合環境變數動態產生,或在 responses 中提供多組 examples

總結

  • 自訂 Example 是提升 FastAPI 文件可用性與專業度的關鍵技巧。
  • 透過 Path / QueryPydantic Fieldschema_extra 以及 responses,我們可以在不同層級提供單一或多組範例,讓 Swagger UI 與 ReDoc 更貼近實務需求。
  • 注意 驗證一致性、避免敏感資訊、保持範例簡潔,並遵循 一致性與可讀性 的寫作規範,能有效減少文件與程式碼不同步的問題。
  • 在實務上,無論是前端快速開發、第三方整合、或是自動化測試,適當的範例都能大幅縮短溝通成本,提升開發效率。

只要掌握本文的概念與範例,你就能在 FastAPI 專案中輕鬆加入高品質的自訂 Example,讓 API 文件不再只是機器產生的說明,而是真正 可讀、可測、可用 的開發資產。祝你寫出更好、更友善的 API!