投稿日
OpenAPI で REST API の定義を作成してみた(Stoplight Studio 使用)
もくじ
はじめに
はじめまして。デザイン&エンジニアリング部の渡邊です。
本記事では案件での OpenAPI の使用経験を元に、OpenAPI で REST API 定義の作成方法をご紹介します。Stoplight Studio という GUI ツールを用いることで、OpenAPI 初心者の方でも簡単に OpenAPI の定義ファイルを作成できます。これから OpenAPI を導入してみたい方や、OpenAPI がどのようなものか知りたい方を中心に活用していただけたら幸いです。
OpenAPI とは
OpenAPI [1] は、REST API の仕様を記述するための標準フォーマットであり、YAML または JSON 形式で API を定義できます。OpenAPI の定義ファイル(以下「OpenAPI 定義」と呼ぶ)には主に下記の仕様を記述します。
- API のエンドポイント
- HTTP メソッド
- リクエスト・レスポンス
作成した OpenAPI 定義からソースコード・テストコード・ドキュメントなどを生成することができ、さまざまな開発プロセスを自動化できます。
OpenAPI の導入理由
私が参画した案件で OpenAPI を導入した理由を説明します。
1点目は開発コストを削減できる点です。私の参画していた案件では SPA 構成の Web アプリケーションを開発していたため、フロントエンド側で API 呼び出しのコードを API ごとに実装する必要があります。OpenAPI を導入する前は、これを手動で一から実装していました。しかし、OpenAPI の導入により OpenAPI 定義からAPI 呼び出しのコードを自動生成することができるようになり、単純作業を減らすことでコストを削減できました。
2点目はフロントエンドとバックエンド間でインターフェースの整合性を保てる点です。OpenAPI 定義からバックエンドのソースコードも自動生成できます。そのため、フロントエンド・バックエンド共に同じ OpenAPI 定義からソースコードを生成することができ、インターフェースの不整合を防ぐことができます。
OpenAPI の構成要素
OpenAPI 定義の構成について、下記のサンプルを元に説明します。
※本記事では全て YAML 形式で記述しています。
openapi: 3.0.0
info:
title: Sample APIs
version: 1.0.0
servers:
- url: http://localhost:8080
paths:
/sample:
get:
summary: サンプル取得API
tags:
- sample
operationId: get-sample
description: サンプルを取得します
responses:
"200":
description: OK
content:
application/json:
schema:
type: object
components: {}
tags:
- name: sample
OpenAPI 定義を構成する主要なフィールドについて説明します。各フィールドで定義する内容は下記の通りです [2] 。
※他にも様々なフィールドが存在しますが、本記事では割愛します。
| フィールド | 必須 | 説明 |
|---|---|---|
| openapi | 〇 | OpenAPI のバージョン |
| info | 〇 | API に関するメタデータ |
| servers | - | API をホストするサーバーの URL |
| paths | 〇 | 各 API のエンドポイントと API の詳細(HTTP メソッド・リクエスト・レスポンスなど) |
| components | - | API 内で再利用可能なパラメータ・リクエスト・レスポンスなど |
| tags | - | API のエンドポイントを分類するためのタグ |
paths 以外のフィールドは各 API で共通の情報を記述し、paths フィールドには各 API の詳細情報を記述します。サンプルでは paths にサンプル取得 API(GET /sample )のみが定義されています。paths 内のフィールドや components については「OpenAPI 定義を作成してみる」で詳しく説明します。
下記の定義は OpenAPI の最小構成 [3] を示しています。必須フィールドのみが記述されており、ここから必要に応じてフィールドを追加していくことができます。
openapi: 3.0.0
info:
title: A minimal OpenAPI Description
version: 0.0.1
paths: {}
OpenAPI 定義を作成してみる
サンプルで用意した API の情報を元に、OpenAPI 定義を作成する方法をご紹介します。案件でも導入している Stoplight Studio というツールを用いて OpenAPI 定義を作成していきます。
Stoplight Studio とは
Stoplight Studio [4] は、OpenAPI 定義を GUI で編集できるツールです。YAML や JSON 形式に慣れていない方でも画面から直感的に OpenAPI 定義を作成することが可能です。無料版も用意されているので、気軽に導入できます [5] 。
定義対象 API
今回はアカウント情報の操作に関する REST API を定義します。この中から「アカウント一覧取得 API」「アカウント更新 API」の定義方法について紹介します。残りの API については説明を割愛しますが、作成した OpenAPI 定義を記事の末尾に載せています。
| API 名 | HTTP
メソッド |
エンドポイント | 説明 | リクエスト | レスポンス |
|---|---|---|---|---|---|
| アカウント一覧取得 API | GET | /accounts | アカウント情報を全て取得する | - | アカウント情報の一覧 |
| アカウント登録 API | POST | /accounts | アカウント情報を新規登録する | アカウント情報 | 登録したアカウント情報 |
| アカウント更新 API | PUT | /accounts/{accountId} | アカウント情報を更新する | アカウント情報 | 更新したアカウント情報 |
| アカウント削除 API | DELETE | /accounts/{accountId} | アカウント情報を削除する | - | - |
アカウント情報は下記の項目が含まれている想定とします。
| 項目名(論理名) | 項目名(物理名) |
|---|---|
| アカウントID | accountId |
| 氏名 | name |
| メールアドレス | |
| 住所 | address |
| バージョン | version |
アカウント一覧取得 API
本記事では、各 API で定義する内容を下記の3つに分けています。
- API 概要
- リクエスト
- レスポンス
それぞれについて Stoplight Studio で定義した内容をお見せし、各設定項目を説明していきます。
▼API概要

各設定項目は下記の通りです。
| 対応する
フィールド |
説明 | 設定値 | 補足 | |
|---|---|---|---|---|
| 1 | tags | API を分類するためのタグ | 「accounts」 | 今回はアカウント情報に関する API のため、エンドポイントと同じ名前を設定 |
| 2 | summary | API 名 | 「アカウント一覧API」 | |
| 3 | - | エンドポイント | 「/accounts」 | |
| 4 | - | HTTP メソッド | 「GET」 | |
| 5 | operationId | API を一意に識別するための文字列 | 「get-accounts」 | Stoplight Studio によって自動入力された値を使用(HTTP メソッドとエンドポイントをハイフンでつなげた値)
OpenAPI 定義からソースコードを自動生成する際、operationId を元に生成される関数やメソッドの名前が決まる |
| 6 | description | API の説明 | 「アカウント情報を全て取得する」 |
ここでは「定義対象 API」に記載された情報を機械的に入力していくことで、定義を作成できます。tags や operationId にも入力ルールを定めておくことで、統一された定義を作成できます。
▼リクエスト
アカウント一覧取得 API はリクエスト項目がないため、設定する項目はありません。
▼レスポンス

各設定項目は下記の通りです。
| 対応する
フィールド |
説明 | 設定値 | 補足 | |
|---|---|---|---|---|
| 1 | - | ステータスコード | 「200」 | 今回は正常系のレスポンスを定義するため「200」を設定
異常系のレスポンスを定義する場合は「+Response」ボタンからステータスコードを追加可能 |
| 2 | description | レスポンスの説明 | 「OK」 | Stoplight Studio によって自動入力された値を使用 |
| 3 | - | レスポンスの形式 | 「application/json」 | JSON 形式でレスポンスする想定 |
| 4 | schema | レスポンス項目 | ※画像参照 | アカウント情報の各項目を設定(物理名と型)
一覧取得 API であるため、配列でアカウント情報をレスポンスする |
| 5 | required | 必須選択 | ※画像参照 | 必須の項目を選択
address 以外は必須項目の想定 |
ここでの設定では、下記のような JSON がレスポンスされることを定義しています。
{
"accountList": [
{
"accountId": "account-01",
"name": "Alice",
"email": "alice@example.com",
"address": "America"
"version": 3
},
{
"accountId": "account-02",
"name": "Bob",
"email": "bob@example.com",
"version": 5
}
]
}
paths:
/accounts:
get:
summary: アカウント一覧取得API
tags:
- accounts
operationId: get-accounts
description: アカウント情報を全て取得する
responses:
"200":
description: OK
content:
application/json:
schema:
type: object
properties:
accountList:
type: array
items:
type: object
properties:
accountId:
type: string
name:
type: string
mail:
type: string
address:
type: string
version:
type: integer
required:
- accountId
- name
- mail
- version
required:
- accountList
アカウント更新 API
続いて、アカウント更新 API のOpenAPI定義を作成していきます。
▼API概要

アカウント更新 API のエンドポイントにはパスパラメータが含まれており、波括弧で囲うことで、Stoplight Studio にパスパラメータとして認識されます。他の項目については、アカウント一覧取得 API と同様に設定します。
▼リクエスト

リクエストの項目はレスポンスと同様に設定できます。
▼レスポンス

アカウント一覧取得 API と同様に設定します。(アカウント更新 API は1件のみアカウント情報をレスポンスします。)
▼作成された OpenAPI 定義
paths:
"/accounts/{accountId}":
parameters:
- schema:
type: string
name: accountId
in: path
required: true
put:
summary: アカウント更新API
tags:
- accounts
operationId: put-accounts-accountId
description: アカウント情報を更新する
requestBody:
content:
application/json:
schema:
type: object
properties:
name:
type: string
mail:
type: string
address:
type: string
version:
type: integer
required:
- name
- mail
- version
responses:
"200":
description: OK
content:
application/json:
schema:
type: object
properties:
accountId:
type: string
name:
type: string
mail:
type: string
address:
type: string
version:
type: integer
required:
- accountId
- name
- mail
- version
リファクタリング
ここまでアカウント一覧取得 API・アカウント更新 API の定義を作成しましたが、両 API のレスポンスのアカウント情報は同一であることが分かります。そこで、「OpenAPI の構成要素」で説明した components フィールドを使用してアカウント情報の型を共通化させます。
▼共通のレスポンス型

Stoplight Studio の「Models」から「ResAccounts」という名前のレスポンス型を追加します。Models に追加した項目は、OpenAPI 定義の components フィールド内の「schemas」フィールドに追加されます。
このレスポンスを使用してアカウント一覧取得 API・アカウント更新 API のレスポンスを共通化させると下記のようになります。
▼アカウント一覧 API のレスポンス

▼アカウント更新 API のレスポンス

▼作成された OpenAPI 定義
paths:
/accounts:
get:
summary: アカウント一覧取得API
tags:
- accounts
operationId: get-accounts
description: アカウント情報を全て取得する
responses:
"200":
description: OK
content:
application/json:
schema:
type: object
properties:
accountList:
type: array
items:
$ref: "#/components/schemas/ResAccounts"
required:
- accountList
"/accounts/{accountId}":
parameters:
- schema:
type: string
name: accountId
in: path
required: true
put:
summary: アカウント更新API
tags:
- accounts
operationId: put-accounts-accountId
description: アカウント情報を更新する
requestBody:
content:
application/json:
schema:
type: object
properties:
name:
type: string
mail:
type: string
address:
type: string
version:
type: integer
required:
- name
- mail
- version
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: "#/components/schemas/ResAccounts"
components:
schemas:
ResAccounts:
title: ResAccounts
type: object
properties:
accountId:
type: string
name:
type: string
email:
type: string
address:
type: string
version:
type: integer
required:
- accountId
- name
- email
- version
このように components フィールドで定義した型は paths フィールド内から参照できます。
レスポンス以外にも、ドメインの型を定義して各項目に紐づけることや、パスパラメータやクエリパラメータを共通的に定義することなどもできます。保守性向上のため、共通化できる項目は components フィールドに定義しておくことをおすすめします。
OpenAPI 定義からドキュメントを生成してみる
「OpenAPI 定義を作成してみる」で作成した OpenAPI 定義を元にドキュメントを生成します。ドキュメント生成には Redocly の build-docs コマンド [7] を使用します。
redocly build-docs [OpenAPI定義のパス] -o [出力先パス]
-o オプションを使用することで出力先パスを指定できます [8] 。
コマンドを実行すると、下記のドキュメントが生成されます。

各 API に accounts タグを付与していることにより、タグごとに API が分類されています。各 API については、OpenAPI 定義で記述した内容を細かく整理された状態で表示できます。ソースコードの自動生成と組み合わせることで、実装とドキュメントの整合性を保つことが容易になります。
ソースコードの自動生成
OpenAPI 定義からソースコードを自動生成する方法については、Fintan の下記記事で紹介されています。これから OpenAPI を導入する方の参考になると思いますので、是非ご覧ください。
OpenAPI の注意点
Git で OpenAPI 定義を管理している場合、ファイルのコンフリクトに注意する必要があります。異なるブランチで異なる API の定義を追加すると、マージした際に高確率でコンフリクトが発生してしまいます。場合によっては絡まった糸を解くような修正をする必要があり、API 定義を作成するのに費やした時間と同じくらいコンフリクト解消に時間がかかることもあります。

この課題に対して私の案件では、「最初に全ての API を仮定義する」という方法を取り、コンフリクトを回避しました。具体的には、各 API のエンドポイントと HTTP メソッドのみを OpenAPI 定義に記述してマージし、その後に各作業者が異なるブランチで各 API の定義を記述するという方法です。複数人で作業する際には効果的なので、是非参考にしてみてください。
Stoplight Studio の注意点
Stoplight Studio を介さずにOpenAPI 定義を直接編集する場合は注意が必要です。Stoplight Studio には下記の特徴があります。
- Stoplight Studio 上の修正 → OpenAPI 定義に即時反映される
- OpenAPI 定義上の修正 → Stoplight Studio を開き直すまで反映されない
そのため、OpenAPI 定義を直接編集した後に Stoplight Studio を開き直さず編集した場合、OpenAPI 定義を直接編集した内容が失われてしまいます。Stoplight Studio を利用していても、YAML 形式で編集した方が都合がよい場合もありますので、その際は忘れずに Stoplight Studio を開き直すように注意してください。また、Stoplight Studio には GUI 以外に YAML 形式で修正できる機能も備わっているので、その機能を使うことで Stoplight Studio を開き直すことなく YAML 形式の修正が可能です [9] 。
まとめ
OpenAPI を使用した REST API の定義方法と OpenAPI 定義からドキュメントを生成する方法について説明しました。Stoplight Studio を利用することで、OpenAPI 初心者の方でも簡単に OpenAPI 定義を作成できることがお分かりいただけたと思います。これから OpenAPI を導入される方の参考になれば幸いです。
また、「OpenAPI 定義を作成してみる」で作成した OpenAPI 定義の全量を次のページに公開していますので、興味のある方は是非ご覧ください。
参考文献
- What is OpenAPI? | Swagger
- Schema | OPENAPI INITIATIVE
- Minimal OpenAPI Description Structure | OPENAPI INITIATIVE
- What is Stoplight Platform? | Stoplight
- API Design Plans and Pricing | Stoplight
- Extensions | Stoplight
- build-docs | Redocly
- build-docs Options | Redocly
- Design Editor Overview | Stoplight
