第1章: OpenAPIとは(歴史・背景・基本概念)
OpenAPIとは、RESTfulなHTTP APIを記述するためのオープンな標準仕様で、もともと Swagger(スワッガー) という名称で2011年に誕生し、APIのエンドポイントやリクエスト/レスポンスの情報を機械可読かつ人間可読な形式で定義するために作られまし た。
OpenAPI仕様で書かれたドキュメント(仕様書)はJSONまたはYAML形式のテキストファイルで表現され、プログラミング言語に依存せずAPIの構造を表現できます。
これにより、APIの設計情報を一元化し、開発者同士のコミュニケーションを円滑にしたり、各種ツールで活用したりすることが可能になります。
OpenAPI仕様書には、APIのエンドポイントURL、利用できるHTTPメソッド(GETやPOSTなど)、各エンドポイントが受け取るパラメータや返すレスポンスの形式、認証方法などをすべて記述します。これによって、**APIの契約(Contract)**が明確化され、開発者はその契約に沿ってクライアントやサーバーの実装を行うことができます。OpenAPI仕様書は人間が読んで理解できるだけでなく、自動生成ツールによってコードやドキュメントに変換できるため、API開発の様々な局面で活用されています。
OpenAPIの歴史: OpenAPI(当時はSwagger)は2011年に米Wordnik社のエンジニアTony Tam氏らによって開発されました。
当初からSwagger UI(後述するAPIドキュメント表示ツール)やコード生成ツール(Swagger Codegen)など、API仕様を書くための周辺ツールが提供されており、APIドキュメントの作成やSDKの自動生成を容易にする目的がありました。
2014年にはSwagger仕様のバージョン2.0が公開され、Swagger Editor(ブラウザ上でSwagger文書を編集・プレビューできるツール)も登場したことで、Swagger仕様はREST API設計の事実上の標準として急速に普及しました。
2015年、Swagger仕様はLinux Foundation傘下のOpenAPI Initiativeに寄贈され、複数企業によるオープンな仕様策定プロジェクトとなりました。
このOpenAPI InitiativeにはSmartBear社(Swaggerを支えてきた企業)やGoogle、IBM、Microsoft、Postmanなど多数の企業が参加し、ベンダーに依存しない中立的なAPI記述フォーマットの推進が図られました。
その後、2017年に新たな名称であるOpenAPI Specification 3.0(OpenAPI仕様3.0)が公開され、Swaggerという名前は主にツール群(Swagger UIやSwagger Editorなど)を指すようになりました。最新の仕様バージョンはOpenAPI 3.1で、2021年にリリースされています。
OpenAPI 3系ではJSON Schemaとの統合強化やセキュリティスキーム定義の改善など、多くの拡張が行われています。現在、OpenAPIは業界標準のAPI記述形式として広く認知されており、他にもRAMLやAPI Blueprintといった仕様がありますが、REST API分野ではOpenAPIが主流となっています。
OpenAPIのメリット: OpenAPIを利用することで、API開発に以下のような利点が生まれます。
- ドキュメント自動生成: OpenAPI仕様書から人間向けのAPIドキュメント(リファレンス)を自動生成できます。例えばSwagger UIを使えば、YAML/JSONの仕様書から見やすいWebドキュメントを即座に生成可能です。
- クライアント/サーバコード生成: OpenAPIから各プログラミング言語向けのAPIクライアントライブラリや、サーバー側のスタブコードを自動生成できます。これにより、手作業のコーディングを減らし、実装漏れを防ぐことができます。
- テストの簡略化: OpenAPI仕様はAPIのリクエストやレスポンスの形式を厳密に定義するため、テストケースを自動生成したり、仕様に基づいたテスト(契約テスト)を行うことが容易になります。
- 例えば、仕様と実装の差異を検出するテストツールも存在します。
- ツールとの連携: OpenAPIは多くのツールと連携可能です。例えば、後述するPostmanに仕様書をインポートして手動テストに利用したり、APIゲートウェイに仕様を入力して設定のベースにすることもできます。
- 設計の明確化とチーム共有: 仕様書という形でAPIの設計を明文化することで、大規模開発での合意形成やチーム内共有が容易になります。フロントエンドとバックエンドで仕様をすり合わせる際にも、OpenAPIが単一の参照源(Single Source of Truth)となります。
以上のように、OpenAPIは単なるドキュメント形式に留まらず、API開発のライフサイクル全体を支える基盤として機能します。
初心者の方も、本書を通じてOpenAPIの全体像を理解し、基本的な仕様書の読み書きやツールでの活用ができるようになることを目指しましょう。
ポイント整理 (第1章)
- OpenAPIはREST APIを記述するためのオープンな標準仕様であり、Swaggerが前身になっています。
- OpenAPI仕様書はJSONまたはYAML形式で書かれ、人間と機械の両方が読める自己文書化されたAPI定義を提供しました。
- 2015年にSwagger仕様がLinux FoundationのOpenAPI Initiativeに寄贈され、名称がOpenAPIに変更されまし。現在最新のバージョンは3.1です。
- OpenAPIを利用すると、APIドキュメントの自動生成、クライアントコードの生成、テストの効率化など様々なメリットが得られました。
- OpenAPI仕様書はAPIの設計情報を一元化した契約書として機能し、チーム開発における認識合わせやツール連携の要となります。
練習問題 (第1章)
- OpenAPI仕様書を記述する際に使用できるデータ形式を2つ挙げてください。
- OpenAPI仕様の前身となったAPI記述仕様の名称は何でしょうか。
- OpenAPIを推進・管理している組織はどこですか。
第2章: OpenAPI仕様の構成要素(パラメータ、レスポンス、認証など)
この章では、OpenAPI仕様書の中身がどのような構成になっているか、主要な要素について説明します。OpenAPI仕様書はYAML/JSON形式の階層構造を持ち、**大きく「メタ情報」、「サーバー情報」、「パス(エンドポイント)定義」、「コンポーネント定義」**などの部分に分かれています。以下、それぞれの要素を初心者向けに解説していきます。
2.1 OpenAPI仕様書の基本構成
OpenAPI仕様書の最上位には以下のような要素があります:
-
openapi: 使用しているOpenAPI仕様のバージョンを示します(例:
"3.0.0"
や"3.1.0"
)。 -
info: APIの基本情報を記述します。タイトル(
title
)、バージョン(version
)、説明(description
)、連絡先やライセンス情報などを含めることができます。 -
servers: APIのサーバーURLを示します。開発環境や本番環境など、ベースとなるURLをリストで指定できます(例:
"https://api.example.com/v1"
)。ここで指定したURLは、パス定義と組み合わさって実際のリクエスト先となります。 - paths: APIのエンドポイント(パス)ごとの定義を記述します。後述するように、各パスの下にHTTPメソッド(operations)をネストさせ、その中でパラメータやレスポンスなどを定義します。
- components: 再利用可能な部品(コンポーネント)を定義するセクションです。具体的には後述するデータスキーマ(Schemas)や共通のレスポンス定義、セキュリティスキームなどをまとめて定義できます。componentsに定義した要素は、後で参照して使い回すことが可能です。
上記は主要なトップレベル要素ですが、この他にもtags
(API操作のグルーピング用)やexternalDocs
(外部ドキュメントへのリンク)などを含めることもできます。まずは基本となるinfo
・servers
・paths
・components
を押さえておきましょう。
2.2 パスとオペレーション(PathsとOperations)
パス (paths): paths
セクションでは、APIの各エンドポイントに対応するパス(URI)をキーとして、その中に複数のHTTPメソッド(操作)を定義します。例えば、/users
というパスに対してGETやPOST、/users/{id}
というパスに対してGET/PUT/DELETEといったように、REST APIで一般的なCRUD操作を定義できます。URI中の中かっこで囲まれた部分(例: {id}
)はパスパラメータと呼ばれ、後述のパラメータ定義で詳細を記述します。
オペレーション (operation): パスの下に記述される各HTTPメソッド(例: GET, POST, PUT, DELETE)は、それぞれが一つの「オペレーション(操作)」を表します。オペレーションには以下のような情報を含めることができます:
-
summary と description: その操作が何をするかの概要(summary)と詳細な説明(description)。
summary
は短い要約、description
にはより詳しい説明を書きます。説明文中にはMarkdown記法を使うこともできます。 -
parameters: その操作が受け取るパラメータの一覧です。パラメータについては後述しますが、クエリパラメータやパスパラメータ、ヘッダーパラメータなどをここで定義します(注意: POSTやPUTなどボディを持つ操作の入力データは
parameters
ではなくrequestBody
で定義します。これについても後述します)。 -
requestBody: 操作が受け付けるリクエストボディの内容を定義します。例えば、POSTで作成するリソースのJSONデータ構造を記述します。
requestBody
には受け入れるメディアタイプ(content
としてapplication/json
など)と、その中で期待されるデータのスキーマを指定します。 -
responses: 操作が返す可能性のあるレスポンスをステータスコードごとに定義します。通常は少なくとも成功時の
200
または201
などのレスポンスを定義し、必要に応じてエラーレスポンス(400番台や500番台)も定義します。各レスポンス定義には、レスポンスの説明(description)と、返される内容のスキーマや例(content
セクションに記述)を含めます。 -
security: その操作に適用するセキュリティ要件(認証)があれば指定します。例えば「このエンドポイントはOAuth2のトークンが必要」などを記述できます。
security
については認証の節で詳説します。 -
tags: 操作にタグ付けを行うことで、Swagger UIなどでドキュメントをグルーピング表示できます。例えば
"users"
タグをつけた操作は「ユーザー」に関するAPIとしてまとめられます。
2.3 パラメータの種類と定義
APIのエンドポイントが受け取るパラメータにはいくつか種類があります。OpenAPIではパラメータを定義する際にname
(名前)とin
(どこで受け取るか)を指定します。主なパラメータの種類は次のとおりです:
-
パスパラメータ (path): URLパスの一部として埋め込まれるパラメータです。例えば
/users/{id}
のid
がパスパラメータに当たります。OpenAPIではin: path
として定義し、さらにrequired: true
とする必要があります(パスパラメータはURL上必須のため省略不可)。型や説明も併せて指定します。 -
クエリパラメータ (query): URLのクエリ文字列(
?
以降)で渡されるパラメータです。例えばGET /users?role=admin&age=20
のrole
やage
が該当します。in: query
として定義し、必要に応じてrequired: true/false
を設定します。型(文字列、整数、ブールなど)やデフォルト値、許容値の範囲なども指定できます。 -
ヘッダパラメータ (header): HTTPヘッダーで渡す追加情報です。標準的なHTTPヘッダー(Content-TypeやAccept等)ではなく、API固有のカスタムヘッダーやトークンの受け渡しに使うヘッダーなどを定義します。
in: header
としてヘッダー名を指定します。ただし、Authorization
ヘッダーなど認証系は後述のセキュリティスキームで扱うことが多いです。 -
クッキーパラメータ (cookie): クッキーを介して渡すパラメータです。利用頻度は高くありませんが、
in: cookie
として定義できます。
各パラメータ定義では、共通して以下の項目を記述できます:
-
name
: パラメータ名(URLやヘッダー上の名前そのまま)。 -
in
: 上記のどこで渡すパラメータか("path"、"query"、"header"、"cookie" のいずれか)。 -
description
: パラメータの説明(用途や意味を書く)。 -
required
: 必須か任意か(boolean値)。pathパラメータは常に必須なのでrequired: true
固定、それ以外は必要に応じ設定。 -
schema
: パラメータのデータ型スキーマ。単純な型ならtype: string
やtype: integer
等で指定します。より複雑なオブジェクト型のパラメータは基本的にbodyで渡すようにするため、query/headerではあまり複雑な構造は使いませんが、配列や列挙型などはここで定義可能です。schemaの指定には後述するJSON Schemaの表記法を用います。
例: クエリパラメータの定義例を見てみましょう。例えば「ユーザー一覧APIで、取得件数の上限を指定するlimit
パラメータ(整数、任意)」を定義する場合:
paths:
/users:
get:
summary: ユーザー一覧の取得
parameters:
- name: limit
in: query
description: 取得する件数の上限
required: false
schema:
type: integer
minimum: 1
maximum: 100
responses:
'200':
description: OK
# ...(レスポンスの定義)...
上記のように、parameters
の配列内にオブジェクトとしてパラメータ定義を記述します。limit
はin: query
で、整数型、1以上100以下という制約付きの例です。required: false
なので指定は任意となります。
2.4 レスポンスの定義
レスポンス (responses): OpenAPI仕様では各操作ごとにresponses
セクションで、HTTPレスポンスをステータスコードごとに定義します。responses
はオブジェクトで、キーにステータスコード(文字列で記述します。例: "200"
、"404"
)を、値にそのレスポンスの詳細定義を持つオブジェクトを書きます。特殊なコードとして、"default"
をキーに指定すると全てのレスポンスコードに共通するデフォルトの定義(エラーハンドリングなど)として扱われますが、基本は具体的なコードごとに定義するのが望ましいです。
各レスポンス定義の中身には以下のような情報を含めます:
-
description: レスポンスの説明文です。例えば
200
であれば「正常に処理できた場合のレスポンス」、400
なら「リクエストが不正な場合のエラー」等を書くことになります。ユーザーに見せるメッセージではなくあくまでドキュメント用の説明です。 -
headers (任意): レスポンスで返すHTTPヘッダーを仕様として定義できます。例えば「ページネーション用の次のページURLを示すカスタムヘッダー」を
headers
に記載すると、Swagger UI上のドキュメントにもそのヘッダーが表示されます。ヘッダー名ごとに型や説明を定義可能です。 -
content: レスポンスボディ(中身)を表現します。通常はこちらが最も重要です。
content
では、まずレスポンスのメディアタイプ(MIMEタイプ)をキーとしてレスポンス内容を記述します。典型的にはapplication/json
が用いられ、値としてそのメディアタイプで返されるデータのスキーマを指定します。例えばapplication/json
の中にschema
を記述し、その中でオブジェクトや配列の構造、フィールドの型などを定義します。必要に応じてexample
(具体的な例)やexamples
(複数例の定義)を示すこともできます。
例: 正常系とエラー系のレスポンス定義例を示します。先ほどのユーザー一覧APIに対し、成功時(200)にユーザーのリスト(JSON配列)を返し、バリデーションエラー時(400)にエラーメッセージを返すような仕様を考えます。
responses:
'200':
description: 正常にユーザー一覧を取得できました
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User' # 後述するUserスキーマを参照
'400':
description: リクエスト不正(クエリパラメータが不正です)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse' # エラー形式のスキーマ参照
上記では、200
レスポンスはJSONの配列を返し、その要素は後で定義するUser
スキーマ型であることを示しています。また400
レスポンスとして、何らかのエラー情報(例えばエラーメッセージやコードを含むオブジェクト)をErrorResponse
というスキーマで返すことを示しています。$ref
はスキーマの参照で、後述するcomponents内の定義を参照しています。
なお、OpenAPIではJSON Schemaという仕様を用いてデータの構造(スキーマ)を記述します。OpenAPI 3.0では基本的にJSON Schema Draft 4相当の書き方を用い、OpenAPI 3.1では最新版のJSON Schema(2020版)との互換性が向上しています。スキーマ定義の詳細は後述しますが、上記例のようにtype: array
やtype: object
、properties
などでデータ構造を明示します。
2.5 認証とセキュリティ定義
- *認証 (authentication)の扱いもOpenAPI仕様の重要なポイントです。APIによってはエンドポイントごと、または全エンドポイント共通で認証/認可が必要な場合があります。OpenAPIでは、認証方式をセキュリティスキーム (security schemes)**として
components
内に定義し、それを各所で適用する形をとります。
セキュリティスキームの定義: components.securitySchemes
において、APIがサポートする認証方式を一つ以上定義できます。主な認証方式とOpenAPIでの指定方法は以下のとおりです:
-
APIキー認証 (API Key): APIキーをHTTPヘッダーやクエリパラメータで渡す方式です。OpenAPIでは
type: apiKey
を指定し、name
にパラメータ名(例:"X-API-Key"
)、in
に渡し方("header"
または"query"
)を指定します。 -
HTTP認証 (HTTP Authentication): Basic認証やBearerトークン認証など、HTTPのAuthorizationヘッダーを使う方式です。
type: http
を指定し、さらにscheme
で"basic"
や"bearer"
を指定します。Bearerトークンの場合は追加でbearerFormat
としてトークン形式(例:"JWT"
)を記述することもできます。 -
OAuth2: OAuth2のアクセストークンを用いる認可方式です。
type: oauth2
を指定し、flows
の中で認可フロー(Authorization CodeやClient Credentialsなど)ごとにトークンURLや認可URL、スコープを定義します。OAuth2は設定項目が多いですが、OpenAPIで詳細な認可要件まで文書化できます。 -
OpenID Connect: OAuth2の上位互換であるOpenID Connectの認証を指定する場合、
type: openIdConnect
とし、openIdConnectUrl
に発行されたOpenID Connect用のDiscovery文書URLを指定します。
例えば、シンプルなAPIキー認証をSecurity Schemeとして定義するYAML例を示します。
components:
securitySchemes:
ApiKeyAuth: # 任意のスキーム名
type: apiKey
in: header
name: X-API-Key
上記では、X-API-Key
というヘッダーでAPIキーを渡す方式をApiKeyAuth
という名前で定義しています。
セキュリティの適用 (security): 認証が必要なエンドポイントには、先ほど定義したセキュリティスキームを適用する必要があります。適用方法は2通りあります。
-
グローバルに適用: OpenAPI仕様書のルート(トップレベル)に
security
セクションを設け、そこに適用するセキュリティスキームを指定します。こうすると、その仕様書内の全エンドポイントに対し、一括でその認証が要求されるという意味になります。 -
個別の操作に適用: 各パスの各操作(メソッド)ごとに
security
を記述し、適用することもできます。特定のエンドポイントだけ認証が必要、または別の認証方法を使う、という場合はこちらで個別に指定します。
security
セクションの書き方は少し特殊で、配列の中にオブジェクトを書きます。各オブジェクトは「ある一組のセキュリティスキーム」を示し、複数書いた場合は「いずれかを満たせばよい(OR)」という扱いになります。通常APIでは一種類の認証だけ使うことが多いので、配列に一つだけオブジェクトを書き、その中で鍵と値の組み合わせとしてscheme名: []
を指定します(値の配列はOAuth2のスコープ指定用で、APIキーやBearerの場合は空配列でOKです)。
先ほどのApiKeyAuth
を全エンドポイントに必須とするなら、トップレベルに以下を追加します:
security:
- ApiKeyAuth: []
こうしておけば、このAPIを利用するにはすべてのリクエストでX-API-Key
ヘッダーに有効なキーを入れなければならない、という契約が明示されます。
例: Bearerトークン(JWT想定)による認証を定義し、一部のエンドポイントに適用する例を示します。
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
paths:
/tasks:
get:
summary: タスクの一覧取得(認証必要)
security:
- BearerAuth: [] # この操作はBearerトークン必須
responses:
'200':
description: OK
# ...(略)...
post:
summary: タスクの新規作成(認証必要)
security:
- BearerAuth: [] # この操作もBearerトークン必須
# ...(略)...
/login:
post:
summary: ログイン(認証不要)
# securityを指定しなければ、この操作には認証不要となる
# ...(略)...
security:
- BearerAuth: [] # もしくは全体に適用したければこちらに記載
上記では、BearerAuth
というセキュリティスキームをJWTトークン用に定義しています。そして、/tasks
のGETとPOSTにそれぞれsecurity
を指定してトークンを要求しています。一方で/login
のようなエンドポイントにはsecurity
を指定していないため、デフォルトでは認証不要(全体適用がなければ)となります。全体に適用するsecurity
も書いた場合、個別の操作でsecurity: []
(空の配列)を指定すると「この操作は認証不要」という意味になります。適切に認証の要否を仕様書に反映させることも、正しいAPI設計において重要です。
2.6 データスキーマ(モデル)の定義
最後に、componentsセクション内のSchemasについて触れておきます。多くの場合、APIはJSON形式でリクエストやレスポンスのデータをやり取りします。その際のデータ構造(モデル)を定義しておくと、仕様書が非常に見やすくなり、再利用性も上がります。components.schemas
にデータモデルを定義しておき、各所で$ref
参照で利用するのが一般的です。
データスキーマの例: 例えば「ユーザー(User)」というリソースオブジェクトを想定し、そのデータモデルを定義してみましょう。ユーザーはid
(整数)、name
(文字列)、age
(整数)という3つの属性を持つものとします。これをOpenAPIのSchemasで定義すると以下のようになります。
components:
schemas:
User:
type: object
properties:
id:
type: integer
name:
type: string
age:
type: integer
required:
- id
- name
ここではUser
という名前でスキーマを定義しました。オブジェクト型(type: object
)であり、properties
の中に各フィールドの型を列挙しています。required
には必須フィールドを配列で指定しています(上記ではid
とname
が必須、age
は任意という意味)。この定義をしておけば、あとは先ほどのように$ref: '#/components/schemas/User'
という形で他の箇所から参照できます。例えばGET /users/{id}の200レスポンスはUser
オブジェクトである、と記述したり、POST /usersのリクエストボディがUser
オブジェクト(ただしid
は不要かもしれませんが)である、のように使い回せます。
スキーマ定義にはより多くのことができます。例えば文字列型にenum
を指定して決められた値のみ許容(列挙型)、整数型にminimum
/maximum
で範囲制約、文字列型にpattern
で正規表現マッチ制約、配列型にitems
で要素の型指定、などなどです。これらは基本的にJSON Schemaの書き方に準拠しています。初心者のうちは、オブジェクトはpropertiesで中身を列挙し、配列はitemsで要素を指定し、プリミティブ型はtypeで型を指定という3パターンを覚えておけば十分でしょう。細かい制約は必要に応じて調べて追記すればOKです。
2.7 ここまでのまとめ
OpenAPI仕様書の構成要素として、API全体の情報 (info
やservers
) から各エンドポイントの詳細 (paths
以下のoperations)、さらには共通定義 (components
) まで一通り説明しました。実際の仕様書ではこれらを組み合わせて、APIの全貌を過不足なく記述していくことになります。最初は情報量が多く感じるかもしれませんが、基本パターンは決まっていますので、章末のポイント整理で改めて要点を確認しましょう。
ポイント整理 (第2章)
- OpenAPI仕様書は、上部に
openapi
バージョンとinfo
(APIのタイトルやバージョン情報)、servers
(APIのURL)、メインにpaths
(各エンドポイント定義)、components
(再利用部品の定義)という構成になっています。 -
pathsセクションでは、各パス(例:
/users
)ごとにHTTPメソッド(GET, POSTなど)を定義し、そこでパラメータ・リクエストボディ・レスポンス・認証要件などを記述します。 -
パラメータにはパス・クエリ・ヘッダー・クッキーの種類があり、
name
とin
で場所を指定して定義します。パスパラメータはURLに含まれるので必須扱いです。 -
レスポンス定義では、HTTPステータスコードごとに説明・レスポンスボディの内容(JSONスキーマ)等を記述します。
content
にメディアタイプ(例: application/json)をキーとしたスキーマを指定して、データの構造を表します。 -
認証の扱いは、
components.securitySchemes
にて認証方式(APIキー、OAuth2、Bearerトークンなど)を定義し、security
セクションで全体または個別のエンドポイントに適用します。これにより、どのエンドポイントでどの認証が必要かを明確に示せます。 -
components.schemasにデータモデル(スキーマ)を定義しておくと、複数のエンドポイントで共通のオブジェクト構造を使い回せます。
$ref
により参照することで、仕様書を簡潔にしつつ一貫性を保つことができます。
練習問題 (第2章)
- OpenAPI仕様書の
info
セクションにはどのような情報を記載する必要がありますか。 - OpenAPIで定義できるパラメータの種類を一つ挙げ、その
in
の値と役割を説明してください。 - HTTP 200のレスポンスをOpenAPIで記述する際、どのような項目を含める必要がありますか(主要な項目を2つ以上挙げてください)。
- APIキー認証をOpenAPIのcomponentsで定義する場合、どのような項目を指定する必要がありますか(主要な項目を2つ以上挙げてください)。
- OpenAPI仕様書でデータ構造(モデル)を再利用可能に定義するには、どのセクションを使用し、どのように参照しますか。
第3章: OpenAPI仕様書の書き方(YAML/JSON形式での例)
前章まででOpenAPI仕様書に盛り込む内容を学びました。ここでは、実際にOpenAPI仕様書をYAML形式およびJSON形式で記述する方法について、具体例を挙げながら説明します。OpenAPIはYAMLとJSONの両方をサポートしていますが、人間が手書きする場合はYAML形式がよく使われます。JSONは機械的に生成したり、プログラムから扱う場合に適しています。両者は表現できる内容は全く同じで、単に記法が異なるだけです。
3.1 YAML形式とJSON形式
YAML形式: YAMLはインデント(字下げ)によってデータのネスト(階層構造)を表現するマークアップ言語です。JSONに比べてクォートや波括弧、カンマなどの記号が少なく、直感的に構造を把握しやすい特徴があります。OpenAPIの公式例などもYAMLで示されていることが多く、実務でもYAMLで仕様書を管理するケースが多いです。
JSON形式: JSONはおなじみのキーと値のペアを波括弧 {}
とコロン :
で記述する形式です。YAMLと一対一で対応しており、YAMLで書かれたOpenAPI仕様書はJSONに変換(シリアライズ)することができますし、その逆も可能です。どちらを使っても最終的な意味内容は変わりません。
以下に、ごく簡単なOpenAPI仕様書のYAML例と、そのJSON表現を並べて示します。同じ内容をそれぞれの形式で表現したものです。
YAMLでの記述例
openapi: "3.0.0"
info:
title: Sample API
version: "1.0.0"
servers:
- url: "http://localhost:8080"
paths:
/hello:
get:
summary: サンプルの挨拶エンドポイント
responses:
'200':
description: 正常なレスポンス
content:
text/plain:
schema:
type: string
JSONでの記述例
{
"openapi": "3.0.0",
"info": {
"title": "Sample API",
"version": "1.0.0"
},
"servers": [
{
"url": "http://localhost:8080"
}
],
"paths": {
"/hello": {
"get": {
"summary": "サンプルの挨拶エンドポイント",
"responses": {
"200": {
"description": "正常なレスポンス",
"content": {
"text/plain": {
"schema": {
"type": "string"
}
}
}
}
}
}
}
}
}
ご覧のように、内容は同じですがYAMLではインデントで構造を表現し、JSONでは波括弧とブラケットで表現しています。YAMLの方が行数は少なく、視覚的にもすっきりしています。一方でJSONは厳密なフォーマットなのでパースしやすく、プログラムから扱いやすいという利点があります。OpenAPI仕様ではどちらを使っても良いので、チームの方針や扱いやすさに応じて選択してください。初心者の方はまずYAMLで書いてみることをお勧めします。
3.2 OpenAPI仕様書の具体的な記述例(YAML形式)
それでは、YAML形式でもう少し実践的な例を見てみましょう。ここではシンプルなTODOリストAPIを想定して、エンドポイントを2つ定義した仕様書の一部を示します。1つはタスク一覧の取得(GET)、もう1つは新規タスクの作成(POST)です。データモデルとして「Task」というオブジェクトを定義し、それを利用しています。
openapi: "3.0.0"
info:
title: TodoリストAPI
version: "1.0.0"
description: |
簡単なTodoリストAPIの仕様書です。
タスクの登録と一覧取得を提供します。
servers:
- url: "http://localhost:8000"
description: ローカル開発用サーバー
paths:
/tasks:
get:
summary: タスク一覧の取得
description: 登録されているタスクのリストを取得します。
responses:
'200':
description: タスク一覧を正常に取得しました
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Task'
post:
summary: 新規タスクの作成
description: 新しいタスクを登録します。
requestBody:
description: 作成するタスクの情報
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Task'
responses:
'201':
description: タスクが正常に作成されました
content:
application/json:
schema:
$ref: '#/components/schemas/Task'
'400':
description: リクエスト内容が不正です
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
components:
schemas:
Task:
type: object
properties:
id:
type: integer
title:
type: string
done:
type: boolean
required:
- id
- title
ErrorResponse:
type: object
properties:
message:
type: string
required:
- message
このYAML例について補足説明します。
-
info
にはタイトル、バージョン、そして複数行の説明を書いています(YAMLでは|
を使うことで改行を含む長い文字列を記述できます)。 -
servers
にはローカルホストのURLを指定し、説明も付けています。 -
paths
の中で/tasks
というエンドポイントに対し、get
とpost
の2つの操作を定義しています。-
get
操作(タスク一覧取得)は、成功時200レスポンスのみを定義し、中身はTask
オブジェクトの配列です(items: $ref: '#/components/schemas/Task'
)。 -
post
操作(新規タスク作成)は、requestBody
を持っています。これはPOSTで受け取るリクエストの内容を定義したもので、application/json
でTask
オブジェクトを受け取る、としています。また、201レスポンス(作成成功)で作成されたタスクオブジェクトを返し、400レスポンス(エラー)でErrorResponse
オブジェクトを返す例も示しています。
-
-
components.schemas
ではTask
とErrorResponse
の2つのスキーマを定義しています。Task
はタスクオブジェクトで、id
(整数),title
(文字列),done
(真偽値)を持ちます。ErrorResponse
は簡単なエラー用オブジェクトで、message
(文字列メッセージ)だけを持ちます。
上記のように、OpenAPI仕様書ではまずデータモデル(TaskやErrorResponse)を定義し、それを使ってリクエストやレスポンスの内容を表現すると理解しやすくなります。特に、同じ構造を繰り返し使う場合は$ref
参照を活用すると良いでしょう。
3.3 JSON形式での記述方法
実際に手でJSONを書いて仕様書を作成するケースは少ないかもしれませんが、YAMLで書いたものを自動的にJSONに変換したり、プログラムの中でJSON構造として扱ったりすることはあります。JSONで書く場合も考え方は全く同じです。先ほどのTodoリストAPIの例をJSON形式にすれば、YAMLのインデントがそのままネストした波括弧に変わり、キーと値がダブルクォートで囲まれ、各要素間にカンマ,
が付く形になります。
JSON形式にする際の注意点は特にありませんが、カンマの付け忘れや波括弧の対応など、純粋にフォーマットエラーに気を付ける必要があります。YAMLの場合はインデント量がずれているとエラーになりますし、JSONの場合は記号の対応が取れないとエラーになります。エディタの機能やオンラインのJSON/YAMLバリデータなどを活用して、書いた仕様書が正しい構文になっているか検証すると良いでしょう。
3.4 OpenAPIエディタ・ツールの活用
OpenAPI仕様書を書く際には、手作業だけでなく専用のツールを使うと効率が上がります。例えばSwagger Editorはブラウザ上で動作するOpenAPI編集ツールで、左側にYAML/JSONを入力すると右側にリアルタイムでドキュメントをプレビュー表示してくれます。また文法エラーがあると指摘してくれるので、初心者が学習するのにも向いています。オフラインでもVSCodeなどのエディタにプラグインを入れれば、YAMLのシンタックスチェックや補完を利用できる場合があります。
また、既存のOpenAPI仕様書を見る機会があれば、それを読んで構造を真似してみるのも上達への近道です。公式のPetstoreサンプル(ペットショップAPIのサンプル)はOpenAPIでよく参照される例なので、一度目を通してみるのもよいでしょう。
ポイント整理 (第3章)
- OpenAPI仕様書はYAML形式で書かれることが多く、インデントによって構造を表現します。JSON形式でも同じ内容を表現できますが、人が編集する際はYAMLの方が見やすい傾向がありま 。
- YAMLとJSONは内容が一対一で対応しており、OpenAPIの情報量や意味に違いはありません。好みや用途に応じて選択できます。
- YAML記述では、インデントやコロン
:
、ハイフンなどの記法に注意しましょう。正しくネストしないとパースエラーになりますが、エディタやオンラインツールで検証できます。 - 具体例として、TodoリストAPIのエンドポイント定義をYAMLで示しました。ポイントは、pathsでエンドポイントごとにメソッドを定義し、components.schemasでデータモデルを定義、それらを
$ref
で参照する形でリクエスト/レスポンスを記述することです。 - Swagger Editorなどの専用ツールを使うと、リアルタイムプレビューやシンタックスチェックができるため、OpenAPI仕様書の学習・作成に役立ちます。
練習問題 (第3章)
- OpenAPI仕様書の記述でYAML形式が好まれるのはなぜですか。
- OpenAPI仕様書の
info
セクションにはどのような情報を含めるべきでしょうか(例を挙げてください)。 - YAMLで書かれたOpenAPI仕様書を検証したりプレビューするのに役立つツールの名前を一つ挙げてください。
- OpenAPI仕様書でデータモデルを再利用するには、どのような記法を用いて参照を行いますか。
第4章: FastAPIでのOpenAPI自動生成と活用方法
OpenAPI仕様書は手書きだけでなく、フレームワークによって自動生成させることもできます。本章ではPythonの人気フレームワークであるFastAPIを題材に、コードからOpenAPIドキュメントを自動生成し活用する方法を紹介します。FastAPIはOpenAPI仕様に準拠したドキュメントを自動生成する機能を備えており、開発者が特別な操作をしなくてもSwagger UIを使ったインタラクティブなAPIドキュメントを提供してくれます。
4.1 FastAPIとは
FastAPIはPython製のWebフレームワークで、特に高速なAPIサーバー構築と型ヒントを用いた宣言的なコーディングが特徴です。FastAPIでは、関数定義と型アノテーションを記述するだけで、自動的にリクエストパラメータのバリデーションや変換が行われます。そしてこの型情報やエンドポイント情報から、**OpenAPI仕様書(JSON)**を起動時に自動生成します。つまり、FastAPIでAPIを実装すると、その実装内容に基づいたOpenAPIドキュメントが常に同期して作られることになります。
4.2 FastAPIによるOpenAPIスキーマの自動生成
FastAPIアプリを起動すると、デフォルトで以下のURLで自動生成されたOpenAPIスキーマやドキュメントにアクセスできます:
-
/docs
– Swagger UIによるインタラクティブドキュメント(HTMLページ) -
/redoc
– ReDocによる静的なドキュメントページ -
/openapi.json
– OpenAPI仕様書そのものをJSON形式で取得できるURL
Swagger UIとReDocはいずれもOpenAPI仕様書を読み込んでレンダリングするドキュメント表示ツールです。FastAPIは標準でSwagger UIとReDocを組み込み、開発者が自前で用意することなくすぐにAPIドキュメントを確認できるようになっています。
たとえばFastAPIで簡単なAPIを実装し、uvicorn
などでローカルサーバーを起動したとします。ブラウザでhttp://127.0.0.1:8000/docs
にアクセスすると、Swagger UIによるAPIインターフェースが表示されま (First Steps - FastAPI)】。またhttp://127.0.0.1:8000/openapi.json
にアクセスすると、自動生成されたOpenAPIのJSONスキーマを見ることができま (First Steps - FastAPI)】。
サンプルコード: 以下に、FastAPIでAPIを実装する簡単な例を示します。この例では、/items/{item_id}
というエンドポイントでGETリクエストを受け取り、クエリパラメータq
を任意指定にしています。
from fastapi import FastAPI
app = FastAPI(title="Sample API", version="0.1.0")
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
"""
アイテムを取得するAPI
- item_id: パスパラメータ(整数)
- q: クエリパラメータ(文字列、任意)
"""
return {"item_id": item_id, "q": q}
上記のコードを実行し、/docs
にアクセスするとSwagger UI画面で自動ドキュメントが確認できます(当然実際にTry it outで動作確認も可能です)。FastAPIはこのコードから自動的に以下のようなOpenAPI仕様を生成しています(概略):
-
paths
に/items/{item_id}
の定義が作られ、get
メソッドが登録される。 - パスパラメータ
item_id
(整数型、必須)とクエリパラメータq
(文字列型、任意)が自動検出され、パラメータ定義に反映される。 -
responses
として、成功時の200レスポンスのスキーマが自動生成される(上記では単にJSONオブジェクト{"item_id": ..., "q": ...}
を返すので、その構造が推論される)。加えて、入力バリデーションエラー用にHTTP 422のレスポンス定義も自動で含まれます。 -
info
にはtitle="Sample API"
やversion="0.1.0"
で指定した内容が反映され、openapi
バージョンはFastAPIのサポートする最新(執筆時点では3.1.0)が設定されます。
(First Steps - FastAPI)】上記のFastAPIコードを実行したSwagger UIの画面例です。item_id
パラメータ(赤字で必須と表示)や、HTTPステータス200と422のレスポンス情報が自動的にドキュメント化されていることが分かります(画面は/docs
にアクセスしたときのSwagger UI)。
FastAPIでは、関数のドキュメンテーション文字列(docstring)や、Query(...)
/Path(...)
といった関数パラメータの宣言で詳細なメタ情報を付けることも可能です。例えばパラメータの説明文やデフォルト値、レスポンスのモデル定義などをコード上に記述しておけば、それらもOpenAPIドキュメントに反映されます。
4.3 自動生成ドキュメントの活用とカスタマイズ
Swagger UIでの活用: Swagger UI上では各エンドポイントの説明やパラメータ・レスポンス仕様が確認できます。そして「Try it out」ボタンを押すことで、ブラウザ上から実際のAPIを呼び出してレスポンスを試すことができます。これは開発中の動作確認や手動テストに非常に便利です。特に、バックエンドAPIを実装しつつフロントエンドの開発者に共有する場合、Swagger UIのURLを教えるだけでAPI仕様を確認してもらえます。
ReDocでの活用: FastAPI標準のもう一つのドキュメントUIであるReDoc(/redoc
)は、Swagger UIと違い読み物としてのドキュメントに適したデザインです。インタラクティブな機能(試し実行)はありませんが、APIの構造を左の目次から辿れて、詳細を右側に表示する形式で、公開用ドキュメントとしてもそのまま使えるクオリティです。
OpenAPI JSONの活用: FastAPIが生成する/openapi.json
には、現在のAPIの完全なOpenAPI仕様書が含まれています。このJSONをそのまま他のツールに渡して活用することも可能です。例えば、後述するPostmanにインポートしてテストに使ったり、別のAPIゲートウェイやドキュメントサービスに登録したり、またはクライアントSDKを生成するために使うこともできます。
実際、FastAPIアプリにアクセスして取得したOpenAPI JSONはopenapi
フィールドやpaths
フィールドを含む標準的なフォーマットで、手書きしたものと同等に扱えます。
カスタマイズ: FastAPIでは自動生成されるOpenAPIドキュメントに対して、いくつかのカスタマイズも可能です。例えば、FastAPI()
クラスのコンストラクタ引数でtitle
やversion
、description
、terms_of_service
、contact
、license
などを指定すれば、それらがそのままOpenAPIのinfo
に反映されます。また、openapi_url
やdocs_url
パラメータで、/openapi.json
や/docs
のパスを変更・無効化することもできます(セキュリティ的に本番環境でdocsをオフにする等の用途)。さらに高度なこととして、app.openapi()
メソッドをオーバーライドして独自にOpenAPIスキーマを変更することもできますが、初心者のうちは既定のままで十分でしょう。
4.4 他の言語・フレームワークでの自動生成
FastAPIの例を紹介しましたが、OpenAPIの自動生成機能は他の言語やフレームワークでも広くサポートされています。例えば、JavaのSpring Bootではアノテーションを付けたコードからOpenAPI(Swagger)ドキュメントを生成する機能がありますし、JavaScript/TypeScriptのExpress用にSwagger定義を書くライブラリ、Ruby on Rails用のドキュメント生成ツールなど様々です。自分の使う技術スタックでOpenAPI対応のツールがあるか調べてみると良いでしょう。
要するに、コードファーストでAPIを実装する場合でも、OpenAPIを活用することで後から正確なドキュメントを得たり、クライアントへの説明を効率化できるわけです。FastAPIはその一例として、とても開発者フレンドリーにドキュメント生成を提供してくれるので、興味があればぜひ使ってみてください。
ポイント整理 (第4章)
- FastAPIはPythonのAPIフレームワークで、API実装から自動的にOpenAPI仕様書(スキーマ)を生成し、ドキュメントページを提供します。
- FastAPIアプリを起動すると、デフォルトで
/docs
(Swagger UI)と/redoc
(ReDoc)という2種類のドキュメントUIにアクセスできます。Swagger UIではAPIをインタラクティブに試すことも可能です。 - FastAPIが生成するOpenAPIスキーマ(
/openapi.json
)は、OpenAPI 3.0/3.1形式のJSONであり、他のツールに取り込んで利用できます。このスキーマにはエンドポイント、パラメータ、モデル、認証方法などがすべて含まれます。 - コード中の型ヒントやパス/クエリの宣言から、自動的にパラメータ定義やレスポンス定義が起こされるため、実装とドキュメントの内容が食い違うリスクが低減します。
- FastAPIでは
FastAPI(title=..., version=...)
のようにしてドキュメント情報を設定でき、Swagger UI上にも反映されます。必要に応じてドキュメントの公開可否やパスも変更可能です。 - OpenAPI自動生成はFastAPI以外の様々な技術でも可能であり、コードファーストのアプローチでもOpenAPIを取り入れることで、開発効率とドキュメント整備を両立できます。
練習問題 (第4章)
- FastAPIで自動生成されるSwagger UIにアクセスするためのURL(エンドポイント)は何ですか。
- FastAPIが起動時に生成するOpenAPI仕様書のURLは何ですか。またその内容はどのような形式で提供されますか。
- FastAPIで自動出力される2種類のAPIドキュメントUIの名称を挙げてください。
- FastAPIのコード中で、OpenAPIドキュメント上のAPIタイトルや説明を設定するにはどのようにすればよいですか。
第5章: PostmanでOpenAPI仕様からAPIを検証する方法
OpenAPI仕様書が用意できたら、それを活用してAPIの動作を検証(テスト)することができます。本章では、APIクライアントツールとして広く使われているPostmanを使って、OpenAPI仕様書からテスト用のリクエスト集を自動生成し、実際にAPIを呼び出して検証する方法を解説します。
5.1 Postmanとは
PostmanはAPIの開発・テスト・文書化に用いられる人気のツールです。GUI上でHTTPリクエストを作成し、APIに送り、返ってきたレスポンスを確認することができます。複数のリクエストをコレクションとして保存したり、スクリプトを書いて自動テストを実行する機能もあります。
Postmanは手動でリクエストを作成するだけでなく、OpenAPIやSwaggerの仕様書をインポートして自動的にリクエストのテンプレート集(コレクション)を作成する機能を持っています。これにより、一つ一つエンドポイントURLやパラメータを設定しなくても、OpenAPI仕様書から全エンドポイント分のリクエストが即座に準備できるのです。
5.2 OpenAPI仕様のインポート手順
PostmanにOpenAPI仕様を取り込むには、以下の手順で行いま (Postman Supports OpenAPI 3.0 | Postman Blog) (ヘルプ:OpenAPIのデータをPostmanにインポートする方法を教えてください - board)】:
- Importの選択: Postmanアプリを開き、画面左上の「Import」ボタンをクリックします。するとデータのインポート用のダイアログが表示されます。
-
ファイル選択またはURL指定: インポートダイアログで、OpenAPI仕様書(YAMLまたはJSON)のファイルを指定するか、もしくはその公開URLを入力します。FastAPIのように
/openapi.json
で取得できる場合は、そのURLを直接指定することも可能です。ローカルファイルの場合はドラッグ&ドロップでも取り込めます。 - インポート実行: ファイルを指定すると、自動的に解析が行われ、OpenAPI 3.0/3.1仕様であればPostman上に「API」として取り込まれます。場合によっては「どのワークスペースに保存するか」等を聞かれるので選択して確定します。
インポートが完了すると、Postman内に新しいコレクションあるいはAPIエントリが作成され、OpenAPIで定義されていた各エンドポイントがフォルダとリクエストのセットとして一覧表示されます。例えば、先ほどのTodoリストAPIの例をインポートしたとすると、GET /tasks
やPOST /tasks
といったリクエストが自動生成され、それらが1つのコレクション(またはAPI項目)内にまとまっている状態になります。
各リクエストには、OpenAPI仕様からパラメータやボディの情報が反映されています。クエリパラメータやヘッダーが定義されていれば、Postmanの該当フィールドにテンプレートとして入っており、値を入力できるようになっています。
ボディが必要なリクエストでは、JSONの例があればそれが設定されているか、少なくとも必要なフィールドが空欄で用意されています。
こちらはOpenAPI仕様をインポートした後のPostman画面イメージです。左側にエンドポイントごとのフォルダとリクエストが生成され、右側には選択したリクエストの詳細(メソッドやURL、パラメータ欄など)が表示されています。たとえばGETリクエストの場合、クエリパラメータの欄にOpenAPIで定義したパラメータ名があり、値を入力できる状態になっています。
5.3 APIを検証する
インポートができたら、実際にAPIサーバーを起動した状態でリクエストを送ってみましょう。Postmanで各リクエストを選択し、必要に応じてパラメータやリクエストボディの値をセットして「Send」ボタンを押すだけです。これにより、OpenAPI仕様書に書かれたエンドポイントに対してHTTPリクエストが発行され、レスポンスが返ってきます。その内容がPostman上で表示されるので、仕様書に記載されたとおりのレスポンスが得られているか確認します。
例えば、GET /tasks
を送ってJSONの配列が返ってくること、POST /tasks
に新規タスクを送って201 Createdが返ってくること、エラーをわざと発生させて400や422エラーが仕様書通りの形式で返ること、などをチェックします。もし実装と仕様が食い違っていれば、この検証で発見できます。たとえば、仕様書ではage
フィールドは整数と書いてあるのに実際のレスポンスが文字列を返していた、といった場合です。その際は実装側の修正か、仕様書の修正が必要になるでしょう。
Postman上では、各リクエストごとにテストスクリプトを書くこともでき、レスポンスのJSONを検証する自動テストを組むことも可能です。しかし初心者段階では、ひとまず手動でレスポンスを見比べて確認するだけでも十分でしょう。
5.4 認証や環境変数の設定
OpenAPI仕様書に認証情報(セキュリティスキーム)が含まれている場合、その内容もPostmanに反映されます。ただし、自動では完全に設定されない部分もあります。例えば、「全てのリクエストにAPIキーを入れる」という仕様だった場合、Postman側ではコレクションレベルで環境変数を用意し、各リクエスト送信前にその変数をヘッダーに注入する、といった対応が必要になることがあります。
具体例として、Bearerトークン認証が必要なAPIをOpenAPIで定義しPostmanにインポートした場合、PostmanはコレクションのAuthorization設定で「Bearer Token」を選択し、トークン部分を{{bearerToken}}
という変数で表現することがあります。
その場合、ユーザーはPostmanのEnvironment(環境変数)にbearerToken
という名前で実際のトークン値を設定してあげれば、各リクエストで自動的にその値がAuthorizationヘッダーに入る仕組みです。APIキーでも似たように、環境変数に値を設定しておき、Pre-request Scriptでヘッダー付与するコードが生成される場合があります。
認証がないシンプルなAPIの場合はそこまで意識しなくて構いませんが、認証付きAPIを試すときは環境変数の設定欄やコレクションのAuthorization設定を確認し、必要な値(APIキーやトークン)を埋めてからリクエストを送りましょう。
5.5 Postmanによる検証のメリット
Postmanを使ったOpenAPI仕様の検証には次のようなメリットがあります:
- 迅速なテスト: 仕様書からボタン一つでテスト環境を構築できるため、実装後すぐに全エンドポイントを網羅的に試せます。手作業でHTTPリクエストを組み立てる手間が省けます。
- 正確なリクエスト: 仕様書由来なので、パスのスペルミスやパラメータ名の間違いが起こりにくいです。実装と仕様の不整合だけに集中できます。
- ドキュメントとしても活用: Postmanに取り込んだコレクションは、そのままチームに共有してドキュメント代わりに使ったり、Mockサーバー機能と組み合わせてフロントエンド開発用の代替サーバーにすることもできます。
- 反復テストが容易: 一度取り込めば、実装が更新された際もまたすぐにテストできます。OpenAPI仕様書も更新して再インポートすれば、コ... (The answer continues from the previous content) ...
反復テストが容易: 一度インポートしておけば、実装を更新した際もすぐに同じコレクションでテストできます。OpenAPI仕様書に変更があった場合でも、更新後の仕様書を再インポートすればPostman上のコレクションを最新化できるため、ドキュメントとテストを常に同期させた状態で開発を進められます。
ポイント整理 (第5章)
- PostmanはGUI上でAPIをテストできるツールで、OpenAPI仕様書をインポートすることでAPIの全エンドポイントを含むテスト用コレクションを自動生成できます。
- インポート後、各エンドポイントはPostman上でフォルダとリクエストの形で一覧表示され、パラメータやリクエストボディもテンプレートとして設定されます。あとは実際の値を入れてSendするだけでAPIを呼び出せます。
- 認証が必要なAPIの場合、Postmanは環境変数やコレクション設定を用いて認証情報を扱います。例えばBearerトークン認証では、変数
bearerToken
を用意してトークン値を設定すれば各リクエストに自動付与されます。 - OpenAPIをインポートしてテストすることで、仕様書と実装の乖離を素早く発見できます。仕様書通りのレスポンスが得られているか、エラーケースは想定通りか、といった点を網羅的にチェックしましょう。
- Postmanに取り込んだコレクションはチームで共有したり、自動テストスクリプトを組んだり、モックサーバー機能に利用したりと、開発フロー全体で活用可能です。
練習問題 (第5章)
- PostmanでOpenAPI仕様書を読み込む際に最初にクリックするボタンの名前は何でしょうか。
- OpenAPI仕様をPostmanにインポートすると、APIの各エンドポイントはPostman上でどのように表示・管理されますか。
- 認証が必要なAPIのOpenAPI仕様をPostmanにインポートした場合、実際にリクエストを送る前にどのような追加設定が必要になることがありますか。
- PostmanにOpenAPI仕様を取り込んでAPIをテストすることのメリットを一つ挙げてください。
第6章: 実践ハンズオン – API設計からドキュメント作成・検証まで
最後に、OpenAPIを用いた実践的な開発の流れを体験してみましょう。ここではこれまで学んだ内容を統合し、シンプルなAPIを題材に設計(OpenAPI仕様作成)→実装→検証という一連の手順を追ってみます。初心者の方でも、小さなAPIでよいので実際に手を動かしてみることで理解が深まるはずです。
6.1 APIの設計 (要件定義)
まずは作りたいAPIの要件を決めます。ここでは例として「ToDoリストAPI」を作成することにしましょう。機能は以下のようにシンプルにします:
-
エンドポイント:
/tasks
- 機能: タスクの新規登録 (POST)、タスク一覧の取得 (GET)
-
データモデル: タスク(Task)オブジェクトは
id
(連番ID),title
(タスクのタイトル),done
(完了フラグ)を持つ
上記のように仕様をざっくり決めます。実際の開発でも、まずはどんなリソース(データ)を扱い、どのような操作(APIメソッド)を提供するかを言葉で整理します。紙に書き出して整理しても良いでしょう。
6.2 OpenAPI仕様書の作成
次に、この要件をOpenAPI仕様書として表現します。テキストエディタやSwagger Editorを使ってYAML形式で書いてみましょう。Chapter 3で説明した内容を踏まえ、TodoリストAPIのOpenAPI仕様書を作成します。
仕様書ドラフト:
openapi: "3.0.0"
info:
title: TodoリストAPI
version: "1.0.0"
paths:
/tasks:
get:
summary: タスク一覧の取得
responses:
'200':
description: 登録されているタスクのリスト
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Task'
post:
summary: 新規タスクの登録
requestBody:
description: 作成するタスク情報
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Task'
responses:
'201':
description: 新しく作成されたタスク
content:
application/json:
schema:
$ref: '#/components/schemas/Task'
'400':
description: 入力データ不正(タイトルが空など)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
Task:
type: object
properties:
id:
type: integer
title:
type: string
done:
type: boolean
required:
- id
- title
Error:
type: object
properties:
message:
type: string
required:
- message
上記は設計したTodoリストAPIの仕様書YAMLです。Chapter 3で扱った例とほぼ同じ内容になっていますが、この段階では細かい説明コメントは省いています。ポイントは、先に仕様書を書くことで「何を実装すべきか」が明確になることです。この仕様書をチームメンバーと確認すれば、「エラー時はどうする?」などの議論も事前にできますし、実装前に不足に気づくこともあります。
今回はPOSTで受け取るTask
オブジェクトにid
も含めていますが、本来id
はサーバー側で採番するのでリクエスト時には不要かもしれません。そうした細かい点も、仕様書を書きながら決めていけます(例えば「Task
スキーマからid
を除いた別のスキーマをリクエスト用に用意する」など)。初心者のうちは深く悩みすぎず、おおまかな形を書いてみることが大事です。後で修正もできます。
仕様書が書けたら、バリデーションをしておきましょう。Swagger Editorに貼り付けてエラーが出ないか確認したり、VSCodeの拡張機能でチェックしたりします。問題なければ次に進みます。
6.3 APIの実装
次に、設計したOpenAPI仕様に沿って実際のAPIサーバーを実装します。ここではFastAPIを使って簡単に実装してみます(他の言語でも構いません)。設計通りに実装することで、OpenAPI仕様書と実装が一致するようにします。
FastAPIによる実装例:
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
app = FastAPI(title="TodoリストAPI", version="1.0.0")
# データモデル(Pydanticモデル)の定義
class Task(BaseModel):
id: int
title: str
done: bool
# 疑似データベース(メモリ内リスト)
tasks_db = []
current_id = 1
@app.get("/tasks", response_model=list[Task])
def get_tasks():
"""タスク一覧を取得する"""
return tasks_db
@app.post("/tasks", response_model=Task, status_code=201)
def create_task(task: Task):
"""新しいタスクを登録する"""
global current_id
# タイトルが空の場合は400エラーを発生させる
if task.title is None or task.title == "":
raise HTTPException(status_code=400, detail="タイトルが空です")
task.id = current_id
current_id += 1
tasks_db.append(task)
return task
上記Pythonコードは非常に簡素化した実装です。本来、POSTで受け取る際にid
は含めずこちらで設定すべきですが、説明を簡単にするためにクライアント側でもid
を送る想定にしています(実際の開発ではTaskCreate
モデルを別途用意するでしょう)。ともあれ、FastAPIではresponse_model
引数にPydanticモデルを指定することで、自動的にOpenAPIのスキーマにも反映されます。また、HTTPException(detail=...)
でエラーを発生させ、そのdetail
メッセージがエラーレスポンスのJSONに含まれます。上記ではタイトルが空なら400を返すようにしています。
コードを書き終えたら、サーバーを起動してみましょう。コマンドラインで uvicorn filename:app --reload
を実行すれば(filenameはこのコードを保存したファイル名)、ローカルサーバーが立ち上がります。ブラウザで http://127.0.0.1:8000/docs
にアクセスすると、FastAPIが生成したSwagger UIが表示されます。内容を確認すると、自分で書いた仕様書とほぼ同じ内容が反映されているはずです(FastAPIが自動生成したOpenAPIも確認できます)。
6.4 APIの検証 (テスト)
最後に、実装が設計通り動いているか検証します。ここではSwagger UIやPostmanを使って動作確認しましょう。
Swagger UIでの確認: FastAPIの/docs
で表示したSwagger UI上で、まずGET /tasks
を試します。初回は空のリストが返るはずです。次にPOST /tasks
をTry it outで実行し、ボディに適当なJSON(例えば{"id": 1, "title": "Sample Task", "done": false}
)を送信します。ステータス201でレスポンスが返り、レスポンスボディに新規タスクが含まれていることを確認します。さらにもう一度GET /tasks
を呼ぶと、先ほど作成したタスクがリストに入って返ってくるでしょう。また、タイトルを空にしたJSONを送ってみてステータス400とエラーメッセージが返るかもチェックします。Swagger UI上でこれらの操作を行えば、仕様書に書いた挙動と実際の挙動が合っているか一通り検証できます。
Postmanでの確認: Swagger UIで動作を確認したら、Postmanでも同様のテストをしてみます。Chapter 5の手順で、作成したFastAPIの/openapi.json
(またはYAML仕様書ファイル)をPostmanにインポートします。するとTodoリストAPIのコレクションができますので、GETとPOSTのリクエストを順番に送り、Swagger UIと同様の結果が得られることを確認します。Postmanでは前回作成したタスクが残っている(メモリに残っている)ので、GETでそのタスクが取得できるはずです。
これらの検証により、設計(仕様書)と実装が整合していることが確認できました。もし齟齬があれば、コードを修正するか仕様書を修正するかして、一致するよう調整します。例えば「本当はPOSTのリクエストではid
は送らない仕様にしたいね」という話になれば、仕様書の方を修正して実装もそれに合わせる、といった具合です。
6.5 まとめ – OpenAPI駆動開発の流れ
ハンズオンの流れをまとめると以下のようになります:
- API要件の定義: どんなAPIを作るか決める(リソース・エンドポイント・操作・データ構造の洗い出し)。
- OpenAPI仕様書の作成: 要件をもとに仕様書を記述する(設計の明文化)。必要に応じてチームでレビューする。
- 実装(コード): 仕様書に沿ってAPIサーバーを実装する。フレームワークの自動生成機能を活用しつつ、エンドポイントやデータモデルをコーディングする。
- 検証・テスト: Swagger UIやPostmanで、実装が仕様書通りに動作するか確認する。不一致があれば修正する。
- 反復(必要なら): 新たな要件変更や機能追加があれば、仕様書→実装→テストのサイクルを繰り返す。
この一連の流れにOpenAPIを取り入れることで、開発の早い段階から正確なドキュメントが存在し、チーム内外への情報共有やテストが容易になります。いわゆるAPIファースト・設計駆動の開発手法を小規模ながら体験できたのではないでしょうか。OpenAPIは、設計書であり、ドキュメントであり、さらにテストやコード生成にも使える多機能なツールです。初心者のうちは全てを活用しきれないかもしれませんが、まずは**「仕様書を書いてみる」**ところから始めてみてください。
本ハンズオンではシンプルなTodo APIでしたが、現実のAPIではもっと多くのエンドポイントや複雑な認証、エラーパターンがあります。そうした場合でも基本的な進め方は同じです。少しずつOpenAPI仕様を書き進め、作っては試しを繰り返すことで、やがてOpenAPIが開発に欠かせない強力な武器となっていることでしょう。
ポイント整理 (第6章)
- 設計ファースト: API開発では、まずOpenAPI仕様書として設計を固め、その後に実装・テストを行う流れが効果的です。これにより実装とドキュメントの不整合を減らせます。
- 小さなAPIでも、OpenAPI仕様書に書き出してみることで必要なエンドポイントやデータ構造が明確化します。事前に検討漏れを洗い出す助けにもなります。
- OpenAPI仕様書に沿って実装する際、FastAPIのようなフレームワークを使えば自動生成されるドキュメントで進捗を確認できます。実装と同時にドキュメントが更新されるので安心です。
- Swagger UIやPostmanを使った動作検証は、設計段階の仕様と実際の挙動を突き合わせる重要なプロセスです。不具合だけでなく、仕様そのものの改善点にも気付けることがあります。
- OpenAPIを活用することで、API設計→実装→テストのサイクルを効率よく回せます。学習段階では小さなAPIから始め、徐々にスキルを高めていきましょう。
練習問題 (第6章)
- API開発において、OpenAPI仕様書を作成するのは開発プロセスのどのタイミングが望ましいでしょうか。
- OpenAPI仕様書に基づいて実装したAPIが、仕様書通りに動作しているか確認するにはどのような方法がありますか。
- ハンズオンで作成したTodoリストAPIのエンドポイントを1つ挙げ、その機能を簡潔に説明してください。
- OpenAPIを用いることで、APIの実装とドキュメントにはどのような関係性・利点が生まれますか。