404 Not Found

404 Not Found


nginx

APIドキュメントとOpenAPIカスタマイズ — プロフェッショナルなAPIドキュメントの作成

APIドキュメントは製品マニュアルのようなものです。なければ顧客 (開発者)は製品を使ってくれません。書き方が悪ければ顧客は足で投票します。自動ドキュメント生成はFastAPIの秘密兵器ですが, デフォルト設定は出発点にすぎず, カスタマイズこそがプロとアマチュアを分けるものです。

1. 学ぶ内容


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生成プロセス

100%
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サブアプリケーションを作成します。

📖 まとめ


📝 練習問題

  1. 基本問題 (難易度 ⭐):PriceTrackerのFastAPIアプリケーションレベルのドキュメントを設定します。タイトル, 説明, バージョン番号, 連絡先情報を含め, persistAuthorization=Trueを追加してSwagger UIの認証状態を保持します。ヒント:FastAPI(title=..., swagger_ui_parameters={...})
  2. 応用問題 (難易度 ⭐⭐):4つのタグ (auth/products/prices/admin)を定義し, 各エンドポイントに正しいタグを割り当て, 非推奨エンドポイントにdeprecated=Trueをマークし, Swagger UIでエンドポイントがタグ別にグループ化されていることを確認します。ヒント:openapi_tags=[...] + tags=["products"]
  3. チャレンジ (難易度 ⭐⭐⭐):ProductCreateにjson_schema_extraの完全な例を追加し, POST /productsエンドポイントにステータスコード201, 401, 403, 422のレスポンステンプレート (サンプルコンテンツを含む)を追加し, カスタムgenerate_unique_id_functionを実装します。ヒント:responses={201: {"content": {...}}} + generate_unique_id_function

---|

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%