1. 基本的な考え方
OpenAPI Specification (OAS) は HTTP API を記述するための標準仕様のセットであり、API は YAML または JSON 形式を使用して定義できます。
OpenAPI ドキュメントには、インターフェイス パス、リクエスト パラメーター、リクエスト本文、応答データ、認証方法、データ モデルなどが記述されています。
OpenAPI、Swagger、Schemaの違い
| コンセプト | 説明 |
|---|---|
| OpenAPI | HTTP APIを記載した標準仕様 |
| Swagger UI | OpenAPI ドキュメントからインタラクティブな API ドキュメントを生成 |
| Swagger Editor | OpenAPI ドキュメントの編集と検証 |
| Swagger Codegen | OpenAPI ドキュメントに従ってクライアントまたはサーバー コードを生成します。 |
| Schema | API リクエスト、レスポンス、データ構造を記述するスキーマ定義 |
OpenAPI 自体は API フレームワークではなく、HTTP リクエストの実行も担当しませんが、機械可読な API コントラクトを提供します。
一般的なワークフロー:
Django REST Framework
↓
drf-spectacular
↓
OpenAPI Schema (YAML / JSON)
↓
┌────┴───────┐
↓ ↓
Swagger UI Orval
↓ ↓
API ドキュメント TypeScript タイプ
API Client / Hooks
このようにして、フロントエンドとバックエンドが同じ API 定義を共有できるため、インターフェイス フィールドの不一致の問題が軽減されます。
2. OpenAPI ドキュメント構造
OpenAPI ドキュメントの主なオブジェクト:
| オブジェクト | 機能 | 必要ですか |
|---|---|---|
| OpenAPI Object | API 定義全体を含むルート オブジェクト | はい |
| Info Object | API の名前、バージョン、説明、その他のメタデータ | はい |
| Paths Object | API パスと HTTP 操作 | はい |
| Servers Object | API サーバーアドレス | いいえ |
| Components Object | 再利用可能なSchema、パラメータ、応答など | いいえ |
| Tags Object | インターフェイスを論理的にグループ化する | いいえ |
| ExternalDocs Object | 外部ドキュメントへのリンク | いいえ |
| Security Requirement Object | API のセキュリティ認証要件に関する声明 | いいえ |
注: security は、OpenAPI ルート オブジェクトまたは Operation Object 内のフィールドであり、paths および components と同じレベルにある独立したトップレベル オブジェクト名ではありません。
OpenAPI 3.0 の最小限のドキュメント:
openapi: 3.0.3
info:
title: Example API
version: 1.0.0
paths: {}
OpenAPI Object
完全な構造例:
openapi: 3.0.3
info:
title: Example API
description: Example REST API
version: 1.0.0
servers:
- url: https://api.example.com/v1
tags:
- name: users
description: User management
paths:
/users:
get:
tags:
- users
summary: Get users
operationId: listUsers
responses:
"200":
description: Successful response
components:
schemas: {}
security: []
このうち、openapi は OpenAPI 仕様のバージョンを表し、info.version は API 自体のバージョンを表します。
3. Info Object
infoはAPIの基本情報を定義します。
info:
title: Example API
description: API documentation example
version: 1.0.0
termsOfService: https://example.com/terms
contact:
name: API Developer
url: https://example.com
email: developer@example.com
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0
| フィールド | 機能 |
|---|---|
| title | APIタイトル |
| description | API の説明、Markdown をサポート |
| version | APIバージョン |
| termsOfService | 利用規約 |
| contact | 連絡先情報 |
| license | ライセンス情報 |
title と version は必須フィールドです。
4. Servers Object
servers は、API のサーバー アドレスを記述します。
複数のサーバーを指定できます。
servers:
- url: https://dev.example.com/api/v1
description: Development
- url: https://staging.example.com/api/v1
description: Staging
- url: https://api.example.com/api/v1
description: Production
サーバー変数を使用する
servers:
- url: https://{environment}.example.com/api/v{version}
variables:
environment:
default: api
enum:
- api
- dev
- staging
version:
default: "1"
enum:
- "1"
- "2"
variables では、変数を使用してサーバー アドレスを定義できるため、異なる環境に対して同様の構成を繰り返し記述する必要がなくなります。
5. Paths ObjectとOperation Object
paths は API へのパスを定義し、各パスには 1 つ以上の HTTP 操作が含まれます。
たとえば:
paths:
/users:
get:
summary: Get users
operationId: listUsers
responses:
"200":
description: Success
post:
summary: Create user
operationId: createUser
responses:
"201":
description: Created
/users/{userId}:
get:
summary: Get user
operationId: getUser
parameters:
- name: userId
in: path
required: true
schema:
type: integer
responses:
"200":
description: Success
Operation Objectの共通フィールド
| フィールド | 機能 |
|---|---|
| tags | インターフェースのグループ化 |
| summary | インターフェースの簡単な説明 |
| description | インターフェースの詳細説明 |
| operationId | インターフェースの一意の識別子 |
| parameters | Path、Query、Header、Cookieパラメータ |
| requestBody | HTTP リクエストボディ |
| responses | HTTP 応答定義 |
| security | グローバルな認証要件をカバー |
| deprecated | インターフェイスが非推奨かどうかをマークする |
| servers | サーバーアドレスを上書きする |
| callbacks | API プロバイダーによって開始されるコールバックについて説明します |
| externalDocs | 外部ドキュメント |
ここで、responses は Operation Object の必須フィールドです。
operationId
operationId: getUserProfile
operationId は、OpenAPI ドキュメント全体で一意である必要があります。
コード生成ツールは、多くの場合、これを使用して関数名を生成します。
たとえば、Orval は次のものに基づいている可能性があります。
operationId: getUserProfile
生成:
getUserProfile();
useGetUserProfile();
生成される特定の結果は、Orval 構成によって異なります。
したがって、安定していて明確で、プログラミングの命名規則と一致している operationId を使用することをお勧めします。
6. Parameters Object
parameters はリクエストパラメータを記述するために使用されます。
次の 4 つのポジションがあります。
| in | パラメータの位置 | 例 |
|---|---|---|
| path | URL パス | /users/{userId} |
| query | クエリ文字列 | ?page=2 |
| header | HTTP Header | X-Request-ID |
| cookie | Cookie | sessionid |
Path Parameter
parameters:
- name: userId
in: path
required: true
description: User ID
schema:
type: integer
in: path の場合、required は true でなければなりません。
Query Parameter
parameters:
- name: page
in: query
required: false
schema:
type: integer
minimum: 1
default: 1
- name: search
in: query
required: false
schema:
type: string
対応するリクエスト:
GET /users?page=2&search=Alice
Parameter 共通フィールド
| フィールド | 機能 |
|---|---|
| name | パラメータ名 |
| in | パラメータの場所 |
| description | パラメータの説明 |
| required | 必要ですか? |
| deprecated | 廃止するかどうか |
| schema | パラメータのデータ構造と検証制約 |
| example | パラメータの値の例 |
| style | パラメータのシリアル化方法 |
| explode | 配列またはオブジェクトのパラメータを展開する方法を制御します |
| allowEmptyValue | 主に Query パラメータに対して NULL 値を許可するかどうか |
配列パラメータのシリアル化
parameters:
- name: ids
in: query
style: form
explode: true
schema:
type: array
items:
type: integer
以下に対応します:
GET /users?ids=1&ids=2&ids=3
設定されている場合:
style: form
explode: false
その後、通常は次のようにシリアル化されます。
GET /users?ids=1,2,3
7. Request Body Object
requestBody は、クライアントによって送信されるデータを記述します。
通常、POST、PUT、PATCH およびその他のリクエストに使用されます。
requestBody:
required: true
description: User information
content:
application/json:
schema:
type: object
required:
- username
- email
properties:
username:
type: string
email:
type: string
format: email
password:
type: string
format: password
example:
username: johndoe
email: john@example.com
password: example-password
parametersとrequestBodyの違い
| 比較する | parameters | requestBody |
|---|---|---|
| 機能 | 独立したリクエストパラメータを記述する | リクエストボディを記述します |
| 場所 | path/query/header/cookie | HTTP Body |
| データ構造 | 通常は単一のパラメータ Schema に対して定義されます | 完全なオブジェクトを定義可能 |
| 一般的な用途 | GET クエリ、パスパラメータ | POST、PUT、PATCH リクエスト |
注: HTTP は、GET リクエストが Body を送信することを絶対に禁止するわけではありませんが、GET Body には普遍的に定義されたリクエスト セマンティクスがありません。 OpenAPI 3.0 は、従来の方法での GET requestBody の定義もサポートしていません。
複数のメディアタイプ
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/User"
application/x-www-form-urlencoded:
schema:
$ref: "#/components/schemas/User"
content では、JSON、フォーム データ、ファイル アップロードなど、複数のメディア タイプを定義できます。
8. Responses Object
responses は、さまざまな HTTP ステータス コードでの API の応答を記述します。
responses:
"200":
description: Successful response
content:
application/json:
schema:
$ref: "#/components/schemas/User"
"400":
description: Invalid request
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
"404":
description: User not found
"500":
description: Internal server error
一般的なステータス コード:
| ステータスコード | 意味 |
|---|---|
| 200 | リクエストは成功しました |
| 201 | リソースが正常に作成されました |
| 202 | リクエストは受け入れられ、非同期的に処理される可能性があります |
| 204 | リクエストは成功しましたが、レスポンスボディはありません |
| 400 | リクエストパラメータエラー |
| 401 | 有効な認証資格情報がありません |
| 403 | アクセス禁止 |
| 404 | リソースが存在しません |
| 409 | リソースステータスの競合 |
| 422 | リクエストの内容を処理できません |
| 500 | サーバー内部エラー |
反応しない体
204 No Contentの場合:
responses:
"204":
description: Successfully deleted
content を定義する必要はありません。
デフォルトの応答
responses:
"200":
description: Success
default:
description: Unexpected error
default では、個別にリストされていない他の応答状況を説明できます。
9. Components Object
components は、OpenAPI の再利用可能なコンポーネント コンテナです。
主に以下が含まれます:
| フィールド | 機能 |
|---|---|
| schemas | 再利用可能なデータモデル |
| parameters | 再利用可能なリクエストパラメータ |
| responses | 再利用可能な応答 |
| requestBodies | 再利用可能なリクエストボディ |
| headers | 再利用可能な応答ヘッダー定義 |
| examples | 再利用可能な例 |
| securitySchemes | 認証メカニズムの定義 |
| links | API 操作間の関係 |
| callbacks | 再利用可能なコールバック |
定義 Schema
components:
schemas:
User:
type: object
required:
- id
- username
properties:
id:
type: integer
username:
type: string
email:
type: string
format: email
再利用可能なパラメータを定義する
components:
parameters:
PageParam:
name: page
in: query
schema:
type: integer
minimum: 1
default: 1
再利用可能な応答を定義する
components:
responses:
NotFound:
description: Resource not found
content:
application/json:
schema:
type: object
properties:
detail:
type: string
10. $ref: コンポーネントリファレンス
$ref は、重複するコードを減らすために、すでに定義されているコンポーネントを参照するために使用されます。
たとえば:
paths:
/users:
get:
operationId: listUsers
parameters:
- $ref: "#/components/parameters/PageParam"
responses:
"404":
$ref: "#/components/responses/NotFound"
Schema 引用:
schema:
$ref: "#/components/schemas/User"
参照パス:
#/components/schemas/User
意味は現在の文書から引用されています。
components
└── schemas
└── User
$ref は、外部ファイルまたは URL の定義の参照もサポートしています。
OpenAPI 3.0 では、Reference Object の他の兄弟フィールドは通常無視されるため、$ref のすぐ隣に description などのフィールドを追加して元の定義をオーバーライドすることはお勧めできません。
11. Schema Object: データモデル
Schema Object は、データ型、フィールド、および検証ルールを記述するために使用されます。
OpenAPI 3.0 の Schema は、すべての JSON Schema キーワードを完全にサポートするのではなく、JSON Schema の拡張サブセットに基づいています。
一般的なデータ型
| タイプ | 意味 | よく使われるformat |
|---|---|---|
| string | 文字列 | date、date-time、email、uuid、binary |
| integer | 整数 | int32、int64 |
| number | 数値 | float、double |
| boolean | ブール値 | — |
| array | 配列 | — |
| object | オブジェクト | — |
format は基本タイプの詳細な説明であり、具体的な検証動作は使用するツールによって異なります。
Schema の完全な例
components:
schemas:
Product:
type: object
required:
- id
- name
- price
properties:
id:
type: integer
format: int64
readOnly: true
name:
type: string
minLength: 1
maxLength: 100
description:
type: string
nullable: true
price:
type: number
minimum: 0
category:
type: string
enum:
- electronics
- books
- clothing
tags:
type: array
items:
type: string
metadata:
type: object
additionalProperties: true
共通の検証フィールド
| フィールド | 説明 |
|---|---|
| required | 必須の属性リスト |
| nullable | null (OpenAPI 3.0) は使用できますか? |
| default | デフォルト値の説明 |
| enum | 許可される値を制限する |
| minimum / maximum | 数値範囲 |
| minLength / maxLength | 文字列の長さの制限 |
| pattern | 正規表現の制約 |
| minItems / maxItems | 配列要素数の制限 |
| uniqueItems | 配列要素は一意ですか? |
| additionalProperties | 追加のオブジェクト プロパティを許可するかどうか |
| readOnly | 読み取り専用フィールド |
| writeOnly | 書き込み専用フィールド |
| deprecated | タグフィールドは非推奨になりました |
requiredとnullableの違い
type: object
required:
- name
properties:
name:
type: string
nullable: true
required: このフィールドはオブジェクト内に存在する必要があります。nullable: 許可されるフィールド値はnullです。
したがって、この例では name を指定する必要がありますが、値 null を許可します。
required リストに記載されていないフィールドは省略できることを意味し、自動的に null が許可されることを意味するものではありません。
12. allOf / oneOf / anyOf
OpenAPI は、キーワードを組み合わせて複雑なデータ構造を構築することをサポートします。
| キーワード | 意味 |
|---|---|
| allOf | Schema をすべて満たす必要があります |
| oneOf | Schema を 1 つだけ満たす必要があります |
| anyOf | 少なくとも 1 人の Schema に会います |
| not | 指定された Schema を満たしていません |
allOf: 組み合わせ Schema
components:
schemas:
Pet:
type: object
required:
- name
properties:
name:
type: string
Dog:
allOf:
- $ref: "#/components/schemas/Pet"
- type: object
properties:
breed:
type: string
Dog は、Pet と新しいフィールド制約の両方を満たします。
allOf はデータ モデルを構成するためによく使用されますが、プログラミング言語レベルでのオブジェクト指向の継承を意味するものではありません。
oneOf: 複数の可能なデータ モデル
schema:
oneOf:
- $ref: "#/components/schemas/Dog"
- $ref: "#/components/schemas/Cat"
データが Schema のいずれかに正確に一致する必要があることを示します。
異なるオブジェクトタイプを区別する必要がある場合は、discriminator と組み合わせて使用できます。
13. Security Schemes
OpenAPI は、components.securitySchemes を使用して認証メカニズムを定義し、次に security を使用してインターフェイスに必要な認証方法を宣言します。
Bearer Token(JWTと共用)
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
security:
- BearerAuth: []
HTTP リクエストに対応:
Authorization: Bearer <token>
bearerFormat: JWT は主にドキュメントのヒントであり、OpenAPI が JWT を自動的に検証することを意味するものではありません。
API Key
components:
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-API-Key
Session Cookie
components:
securitySchemes:
SessionAuth:
type: apiKey
in: cookie
name: sessionid
この方法では、Cookie 経由で渡される資格情報が記述されていますが、実際の Session 検証は依然としてバックエンドによって行われます。
また、CSRF Token は、securitySchemes を定義するだけでは保護機能を獲得しません。
単一インターフェースの認証をオーバーライドする
paths:
/public:
get:
security: []
responses:
"200":
description: Success
security: [] は、この操作によって継承されたグローバル セキュリティ要件が削除されることを示します。
14. TagsとExternalDocs
Tags: インターフェースのグループ化
tags:
- name: users
description: User management
- name: products
description: Product management
paths:
/users:
get:
tags:
- users
responses:
"200":
description: Success
Tags は主に Swagger UI などのドキュメント ツールのインターフェイス分類に使用されます。
ExternalDocs: 外部ドキュメント
externalDocs:
description: Additional API documentation
url: https://example.com/docs
外部文書情報は、最上位レベル、操作内、または部分的な Schema 定義で提供できます。
15. ファイルアップロード: multipart/form-data
ファイルのアップロードには通常、multipart/form-data を使用します。
paths:
/users/avatar:
post:
summary: Upload avatar
operationId: uploadAvatar
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required:
- file
properties:
file:
type: string
format: binary
responses:
"200":
description: Upload successful
重要なポイント:
type: string
format: binary
バイナリファイルフィールドを表します。
Django REST Framework の場合、これは通常、次のものと組み合わせることができます。
from rest_framework.parsers import MultiPartParser
アップロードリクエストを処理します。
16. drf-spectacularとDjango REST Framework
drf-spectacular は、View、Serializer、URL および DRF のその他の情報に基づいて、OpenAPI Schema を自動的に生成できます。
基本構成
# settings.py
INSTALLED_APPS = [
"rest_framework",
"drf_spectacular",
]
REST_FRAMEWORK = {
"DEFAULT_SCHEMA_CLASS":
"drf_spectacular.openapi.AutoSchema",
}
SPECTACULAR_SETTINGS = {
"TITLE": "Example API",
"DESCRIPTION": "REST API documentation",
"VERSION": "1.0.0",
}
API ドキュメント ルーティングを構成する
# urls.py
from django.urls import path
from drf_spectacular.views import (
SpectacularAPIView,
SpectacularSwaggerView,
SpectacularRedocView,
)
urlpatterns = [
path(
"api/schema/",
SpectacularAPIView.as_view(),
name="schema",
),
path(
"api/docs/",
SpectacularSwaggerView.as_view(
url_name="schema"
),
name="swagger-ui",
),
path(
"api/redoc/",
SpectacularRedocView.as_view(
url_name="schema"
),
name="redoc",
),
]
これらのルートは次の目的で使用されます。
/api/schema/: OpenAPI Schema を取得します。/api/docs/: Swagger UI を表示します。/api/redoc/: ReDoc のドキュメントを表示します。
extend_schema
@extend_schema は、自動生成された OpenAPI 情報を補足または上書きするために使用されます。
from drf_spectacular.utils import (
extend_schema,
OpenApiParameter,
OpenApiTypes,
)
from rest_framework.views import APIView
from rest_framework.response import Response
class UserView(APIView):
@extend_schema(
tags=["Users"],
summary="Get user",
operation_id="getUser",
parameters=[
OpenApiParameter(
name="user_id",
type=OpenApiTypes.INT,
location=OpenApiParameter.QUERY,
required=True,
)
],
responses={200: UserSerializer},
)
def get(self, request):
...
パラメータ、リクエストボディ、レスポンスボディ
extend_schema:
| パラメータ | OpenAPIに対応 |
|---|---|
parameters | Parameter Object |
request | Request Body Object |
responses | Responses Object |
operation_id | operationId |
summary | summary |
description | description |
tags | tags |
deprecated | deprecated |
たとえば:
@extend_schema(
operation_id="createUser",
request=UserCreateSerializer,
responses={
201: UserResponseSerializer,
400: ErrorSerializer,
},
)
def post(self, request):
...
extend_schema_view
クラス レベルで複数のメソッドに対して Schema を指定する必要がある場合:
from drf_spectacular.utils import (
extend_schema,
extend_schema_view,
)
@extend_schema_view(
get=extend_schema(
operation_id="listUsers",
responses=UserSerializer(many=True),
),
post=extend_schema(
operation_id="createUser",
request=UserCreateSerializer,
responses={201: UserSerializer},
),
)
class UserView(APIView):
...
extend_schema_viewは、Viewで複数の演算を統一的に記述するのに適しています。
OpenAPIファイルを生成する
python manage.py spectacular \
--file schema.yaml \
--validate
生成された schema.yaml は次の用途に使用できます。
- Swagger UI
- ReDoc
- Orval
- OpenAPI Generator
- API Schemaチェック
Schema の検証が成功したということは、ドキュメントが基本的に仕様に準拠していることを意味するだけであり、API の実際の動作がドキュメントと完全に一致することを保証するものではないことに注意してください。
17. OpenAPI とフロントエンド コード生成
React + TypeScript プロジェクトの場合、Orval を使用して、OpenAPI Schema に基づいて API Client と型定義を自動的に生成できます。
Django Serializer
↓
drf-spectacular
↓
OpenAPI Schema
↓
Orval
↓
TypeScript Types
Axios Functions
TanStack Query Hooks
バックエンドの例:
@extend_schema(
operation_id="getUser",
responses=UserSerializer,
)
フロントエンドは以下を生成する場合があります。
getUser();
useGetUser();
このアプローチの主な価値は次のとおりです。
- フロントエンドとバックエンドでのインターフェイス タイプの繰り返し定義を減らします。
- リクエストとレスポンスのタイプの安全性を向上させます。
- API Clientのメンテナンスを簡素化します。
- 一貫性のないフィールド名が発生するリスクを軽減します。
ただし、注意してください: OpenAPI Schema は単なるインターフェイス コントラクトであり、生成された TypeScript 型は、サーバーが実行中に Schema に準拠するデータを返すことを保証しません。
したがって、バックエンドでのデータの検証、テスト、および Schema の精度は依然として重要です。
18. OpenAPI 3.0と3.1の違い
OpenAPI 3.1 では、JSON Schema Draft 2020-12 との一貫性を高めるために、Schema のサポートに重要な調整が行われています。
| 特長 | OpenAPI 3.0 | OpenAPI 3.1 |
|---|---|---|
| Schemaの基本 | JSON Schema 拡張サブセット | アライメント JSON Schema 2020-12 |
| nullable | nullable: trueを使用してください | 通常、null を表すには共用体型が使用されます。 |
| JSON Schema キーワード | 限定的なサポート | サポートがさらに充実 |
| Schemaの互換性 | OpenAPIの固有制約に注意が必要 | 標準のJSON Schemaに近い |
OpenAPI 3.0:
type: string
nullable: true
OpenAPI 3.1:
type:
- string
- "null"
また、OpenAPI 3.1では、$refなどの関連機構もさらに改善されました。
実際の開発においては、使用するドキュメントツールやコードジェネレータとの互換性を考慮して OpenAPI バージョンを選択する必要があり、必ずしもすぐに最新バージョンにアップグレードする必要はありません。
概要
OpenAPI の中心的な内容は 4 つの部分に分けることができます。
| 分類 | フォーカス |
|---|---|
| 文書構造 | OpenAPI、Info、Servers、Paths |
| インターフェースの定義 | Operation、Parameters、RequestBody、Responses |
| データモデル | Schema、Components、$ref、allOf、oneOf |
| エンジニアリングの実践 | SecuritySchemes、Swagger UI、drf-spectacular、Orval |
最も習得する必要があるのは次のとおりです。
pathsおよび Operation Object: インターフェースについて説明します。parametersおよびrequestBody: 説明入力。responsesおよびschemas: 出力とデータ構造を説明します。componentsおよび$ref: コンポーネントの再利用を実装します。operationId: 安定したクライアント コード生成をサポートします。securitySchemes: インターフェイスの認証要件について説明します。
Django + DRF 開発の場合は、メインのデータ構造定義として Serializer を使用し、OpenAPI Schema から drf-spectacular までを自動的に生成し、最後にそれを Swagger UI および Orval に渡して使用することをお勧めします。