APIドキュメントとOpenAPIカスタマイズ — プロフェッショナルなAPIドキュメントの作成
APIドキュメントは製品マニュアルのようなものです。なければ顧客 (開発者)は製品を使ってくれません。書き方が悪ければ顧客は足で投票します。自動ドキュメント生成はFastAPIの秘密兵器ですが, デフォルト設定は出発点にすぎず, カスタマイズこそがプロとアマチュアを分けるものです。
1. 学ぶ内容
- Swagger UIとReDoc設定:
swagger_ui_parameters, カスタムJS/CSS - OpenAPI Schemaカスタマイズ:
openapi_route, カスタムgenerate_unique_id_function description/summary/tags/deprecatedのベストプラクティス- サンプル値とレスポンステンプレート:
OpenApiResponse+json_schema_extra - Aliceシナリオ:PriceTrackerのプロフェッショナルSaaS APIドキュメント
2. Aliceのリアルストーリー
(1) ペインポイント:デフォルトのドキュメントではプロフェッショナルさに欠ける
AliceのPriceTracker APIドキュメントはFastAPIのデフォルトSwagger UIを使用しており, すべてのエンドポイントがグループ化されずに混在しており, Bobは必要なエンドポイントを見つけられません。さらに悪いことに, ドキュメントにサンプルリクエストがなく, Bobはcurrencyフィールドに何を入力すればよいかわかりません。リクエストやレスポンスボディのバージョニングもなく, 新しいエンドポイントと非推奨エンドポイントが混在しています。
(2) OpenAPIカスタマイズのソリューション
FastAPIではOpenAPIドキュメントの深いカスタマイズが可能です。タググループ化, サンプル値, 非推奨マーカー, カスタムスキーマなどにより, APIドキュメントを「読める」ものから「使える」ものに変えることができます。
(3) 収益
Bobはドキュメントを開くだけで, タグ (Products/Prices/Auth)別にエンドポイントを素早く見つけられます。サンプル値によりリクエスト時の推測が不要になり, 非推奨エンドポイントはグレーで表示されるため誤用を防げます。ドキュメントの品質が「社内参考」レベルから「公開リリース」レベルに引き上がりました。
3. Swagger UIとReDoc設定
(1) OpenAPI生成プロセス
flowchart LR
A[FastAPI Routes] --> B[Pydantic Models]
B --> C[OpenAPI 3.1 Schema]
C --> D[Swagger UI /docs]
C --> E[ReDoc /redoc]
C --> F[Raw JSON /openapi.json]
(1) ▶サンプル:FastAPIアプリケーションレベルのドキュメント設定
PYTHON
from fastapi import FastAPI
app = FastAPI(
title="PriceTracker API",
description="""
## PriceTracker SaaS API
E-commerce price tracking service for monitoring million-level product prices.
### (1) Authentication
All protected endpoints require a Bearer token obtained from `/auth/login`.
### (2) Rate Limits
- Free: 100 requests/min
- Pro: 1000 requests/min
- Enterprise: unlimited
""",
version="1.0.0",
terms_of_service="https://pricetracker.example.com/terms",
contact={
"name": "PriceTracker Support",
"url": "https://pricetracker.example.com/support",
"email": "support@pricetracker.example.com",
},
license_info={
"name": "MIT License",
"url": "https://opensource.org/licenses/MIT",
},
docs_url="/docs",
redoc_url="/redoc",
openapi_url="/openapi.json",
)
出力:
TEXT
# 実行成功
(3) ▶サンプル:Swagger UIパラメータのカスタマイズ
PYTHON
app = FastAPI(
swagger_ui_parameters={
"persistAuthorization": True, # ページ更新時に認証を保持
"displayRequestDuration": True, # リクエスト所要時間を表示
"filter": True, # 検索フィルターを有効化
"syntaxHighlight.theme": "monokai", # コードハイライトテーマ
"defaultModelsExpandDepth": 1, # モデルを1レベル展開
"defaultModelExpandDepth": 1,
}
)
出力:
TEXT
# 実行成功
| パラメータ | デフォルト | 説明 |
|---|---|---|
persistAuthorization |
False | ページ更新時に認証を保持 |
displayRequestDuration |
False | リクエスト所要時間を表示 |
filter |
False | 検索フィルターを有効化 |
defaultModelsExpandDepth |
1 | モデル展開深度 |
syntaxHighlight.theme |
"agate" | コードハイライトテーマ |
4. タググループ化と非推奨マーカー
(1) タグ:エンドポイントのグループ化
(1) ▶サンプル:タグの定義
PYTHON
from fastapi import FastAPI, APIRouter
tags_metadata = [
{
"name": "auth",
"description": "Authentication operations. Login, register, token refresh.",
},
{
"name": "products",
"description": "Product management. CRUD operations for tracked products.",
},
{
"name": "prices",
"description": "Price data. Query, import, and track price changes.",
},
{
"name": "admin",
"description": "Admin operations. Requires admin role.",
},
]
app = FastAPI(
title="PriceTracker API",
openapi_tags=tags_metadata,
)
出力:
TEXT
# 実行成功
(2) ▶サンプル:エンドポイントへのタグ割り当て
PYTHON
@app.post("/auth/login", tags=["auth"])
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
...
@app.get("/api/v1/products", tags=["products"])
async def list_products():
...
@app.post("/api/v1/prices", tags=["prices"])
async def create_price():
...
@app.get("/api/v1/admin/stats", tags=["admin"])
async def admin_stats():
...
出力:
TEXT
# 関数定義成功
(3) ▶サンプル:エンドポイントの非推奨マーキング
PYTHON
@app.get(
"/api/v1/products/{product_id}/history",
tags=["prices"],
deprecated=True,
summary="[DEPRECATED] Use GET /prices?product_id={id} instead",
)
async def get_price_history_deprecated(product_id: int):
"""This endpoint is deprecated. Use the prices endpoint with product_id filter."""
...
出力:
TEXT
# 関数定義成功
5. サンプル値とレスポンステンプレート
(1) json_schema_extraとexamples
(1) ▶サンプル:Pydanticモデルのサンプル値
PYTHON
from pydantic import BaseModel, Field
class ProductCreate(BaseModel):
name: str = Field(
min_length=1, max_length=200,
description="Product display name",
examples=["Wireless Mouse", "USB-C Hub", "Mechanical Keyboard"],
)
category: str = Field(
max_length=100,
description="Product category",
examples=["electronics", "clothing", "food"],
)
base_price: float = Field(
gt=0,
description="Base price in USD",
examples=[9.99, 49.99, 199.99],
)
model_config = {
"json_schema_extra": {
"examples": [
{
"name": "Wireless Mouse",
"category": "electronics",
"base_price": 29.99,
}
]
}
}
出力:
TEXT
# 実行成功
(2) ▶サンプル:エンドポイントレベルのレスポンス例
PYTHON
from fastapi import FastAPI
from fastapi.responses import JSONResponse
@app.post(
"/api/v1/products",
response_model=ProductResponse,
status_code=201,
summary="Create a new product",
description="Create a new product in the PriceTracker database.",
responses={
201: {
"description": "Product created successfully",
"content": {
"application/json": {
"example": {
"id": 1,
"name": "Wireless Mouse",
"category": "electronics",
"base_price": 29.99,
}
}
},
},
401: {"description": "Authentication required"},
403: {"description": "Insufficient permissions"},
422: {"description": "Validation error"},
},
)
async def create_product(product: ProductCreate):
...
出力:
TEXT
# 関数定義成功
6. カスタムOpenAPI Schema
(1) generate_unique_id_function
(1) ▶サンプル:カスタムエンドポイントIDの生成
PYTHON
from fastapi import FastAPI
def custom_generate_unique_id(route):
# フォーマット:{method}_{tag}_{path}
tags = route.tags or ["default"]
tag = tags[0]
method = route.methods.pop() if route.methods else "GET"
path = route.path.replace("/", "_").strip("_").replace("{", "").replace("}", "")
return f"{method}_{tag}_{path}"
app = FastAPI(
generate_unique_id_function=custom_generate_unique_id,
)
出力:
TEXT
# 関数定義成功
(2) ドキュメントベストプラクティスの比較
| 項目 | デフォルト | ベストプラクティス |
|---|---|---|
| エンドポイントグループ | なし | 機能別タグ |
| 非推奨エンドポイント | 通常エンドポイントに混在 | deprecated=Trueグレーマーク |
| リクエスト例 | なし | examples + json_schema_extra |
| レスポンステンプレート | 200のみ | 201/401/403/422の完全カバー |
| 説明 | 単純な関数名 | summary + description |
| 認証情報 | なし | ドキュメントホームページに認証方法の説明 |
| バージョニング | 単一バージョン | URLパスバージョン /api/v1/ |
❓ よくある質問
Q Swagger UIとReDocの違いは何ですか?
A Swagger UIはインタラクティブ (APIをテスト可能), ReDocは閲覧向け (より見やすい)です。外部向けドキュメントにはReDoc, 内部開発にはSwagger UIを推奨します。
Q 特定のエンドポイントをドキュメントに表示しないようにするにはどうすればよいですか?
A
include_in_schema=Falseを設定します:@app.get("/internal", include_in_schema=False)。内部ヘルスチェックやモニタリングエンドポイントに適しています。Q OpenAPIバージョン3.0と3.1のどちらを使うべきですか?
A FastAPIはデフォルトでOpenAPI 3.1を生成します (最新のJSON Schema機能をサポート)。古いツールとの互換性が必要な場合は, カスタム
openapi関数でバージョンをダウングレードできます。Q ドキュメントにカスタムCSS/JSを追加するにはどうすればよいですか?
A
swagger_ui_parametersでCSS URLを指定するか, get_swagger_ui_htmlでHTMLを完全にカスタマイズします。Q サンプル値とデフォルト値の違いは何ですか?
A 「examples」はドキュメント目的であり検証に影響しません。「default」は実際のデフォルト値であり動作に影響します。両方を設定すべきです。
Q 複数APIバージョンのドキュメントはどう整理すべきですか?
A 各バージョンに個別の
APIRouter(prefix="/api/v1")を使用し, タグでバージョンを区別します。または, 各バージョンに個別のFastAPIサブアプリケーションを作成します。📖 まとめ
- FastAPIはOpenAPI 3.1ドキュメントを自動生成し, Swagger UIがインタラクティブテストを提供し, ReDocが見やすい閲覧体験を提供します
openapi_tagsでエンドポイントを機能別にグループ化,deprecated=Trueで非推奨エンドポイントをマークField(examples=[...])とjson_schema_extraでモデルにサンプル値を追加responses={status: {description, content}}でエンドポイントに複数ステータスコードのレスポンステンプレートを定義- カスタム
generate_unique_id_functionでOpenAPIオペレーションIDの命名形式を制御
📝 練習問題
- 基本問題 (難易度 ⭐):PriceTrackerのFastAPIアプリケーションレベルのドキュメントを設定します。タイトル, 説明, バージョン番号, 連絡先情報を含め,
persistAuthorization=Trueを追加してSwagger UIの認証状態を保持します。ヒント:FastAPI(title=..., swagger_ui_parameters={...}) - 応用問題 (難易度 ⭐⭐):4つのタグ (auth/products/prices/admin)を定義し, 各エンドポイントに正しいタグを割り当て, 非推奨エンドポイントに
deprecated=Trueをマークし, Swagger UIでエンドポイントがタグ別にグループ化されていることを確認します。ヒント:openapi_tags=[...]+tags=["products"] - チャレンジ (難易度 ⭐⭐⭐):ProductCreateに
json_schema_extraの完全な例を追加し, POST /productsエンドポイントにステータスコード201, 401, 403, 422のレスポンステンプレート (サンプルコンテンツを含む)を追加し, カスタムgenerate_unique_id_functionを実装します。ヒント:responses={201: {"content": {...}}}+generate_unique_id_function
---|



