1. はじめに
本題に入る前に、前提となることを記述しておきます。
この記事は、徐々に仕様書ができていく様を表示しています。
そのため、行数が多くなっています。
1.1. 結論
この記事の結論を先に書いてしまいます。
結論は以下です。
- 以下のステップでOpenAPIが書ける。
- メタ情報を書く
- パス情報を書く
- コンポーネントで整形する
1.2. 目的
目的は以下です。
- OpenAPI3.0を書けるようにする
1.3. 読者の対象
読者の対象は以下です。
- APIの仕様書を軽く理解したい方
- プログラミング初心者
- OpenAPI3.0の書き方をググったけど、英語ドキュメントばかりでわからない方
- 以下の基本知識がある方(参考にしているチュートリアルに記載されています)
- REST API
- YAML形式
1.4. 参考
2. 本題
基本的に、SwaggerHubに書かれているOpenAPI3.0チュートリアル(上記「参照」のチュートリアル)に沿って記載しています。
なお、ここで説明するパラメーターは、チュートリアルに登場するパラメーターのみです。
すべてのパラメーターについては公式Documentation(上記「参照」のDocumenatation)を参照してください。
2.1. OpenAPIとは
- オープンソースのフォーマットで、APIの仕様を記述するもの。
- REST APIの仕様を記述するデファクトスタンダード。
- JSON形式とYAML形式のどちらでも記述できる。
- SwaggerHubとしてはYAML形式を推奨している(容易に読み書きできるため)。
ここでは、タイトルにあるように、OpenAPI 3.0の説明をしていきます。
OpenAPIの最新バージョンは、「OpenAPI-Specificationリリースノート」を参照してください。
2.2. APIを作ってみる
では早速作ってみましょう。
まずは、OpenAPI 3.0で記述される仕様書がどのようなものなのか、説明します。
OpenAPI 3.0では、定義ファイルが以下3つのセクションに分かれます。
- メタ情報
- パス情報(エンドポイント)
- パラメーター
- リクエストボディ
- レスポンス
- コンポーネント
- スキーマ(データモデル)
- パラメーター
- レスポンス
- その他のコンポーネント
それぞれの項目について、以下で説明します。
なお、以降で記載するサンプルYAMLは、チュートリアル記載のファイルとは異なる、自作のものです。
何に関するアプリケーションを作っているか、ご想像にお任せします。
2.2.1. メタ情報
作成するAPIがどういうものなのか、つまり情報についての情報(=メタデータ)を記述するセクションです。
サンプルコード
openapi: 3.0.0
info:
version: 1.0.0
title: Training Menu API
description: A simple menu for exercise
servers:
- url: http://localhost/training/v1
各パラメーターについて説明します。
パラメーター | 説明 |
---|---|
openapi |
使用するOpenAPIのバージョンを記載する。ここでは3.0.0を使っている。 バージョンは、OpenAPIのリリースノートを参照してください。 |
info |
OpenAPIで記述したい内容を記載するオブジェクト。主なパラメーターは以下。 ・必須パラメーター: version 、 title ・任意パラメーター: description
|
title |
必須パラメーター。このAPI仕様書を用いて作成するアプリケーションのタイトル。 |
version |
必須パラメーター。アプリケーションのバージョン(OpenAPIのバージョンとは関係ない。アプリケーションのバージョンである。) |
description |
任意パラメーター。アプリケーションについての説明 |
servers |
APIターゲットホストサーバー情報を記載するオブジェクト。必須パラメーターとしてurl がある。 |
url |
必須パラメーター。APIターゲットホストのURL。 |
他にもセキュアな認証認可を実現するAPIパラメーターもありますが、ここでは割愛します(ローカルホスト内エンドポイントを想定しているため)。
2.2.2. パス情報
エンドポイントやメソッドを記述するところです。
サンプルコード
openapi: 3.0.0
info:
version: 1.0.0
title: Training Menu API
description: A simple menu for exercise
servers:
- url: http://localhost/training/v1
#---ここから追加---
paths:
/plans:
get:
description: Return a list of training plans
#---ここまで追加---
各パラメーター/値について説明します。
パラメーター/値 | 説明 |
---|---|
paths |
エンドポイントを記載するオブジェクト。 パスとして /plans を定義している。また、パス /plans に対してGETメソッドを定義する。 |
/plans |
サンプルYAMLではパスパラメーターに値/plans を定義している。 |
get |
REST APIのメソッド。ここではパス/plans に対し、 GET メソッドを定義している。 |
desctiption |
任意パラメーター。パス/plans に対し定義したGET メソッドについての説明。 |
ここまででわかることは、
「クライアントはトレーニングプラン一覧を取得するために、GET http://localhost/training/v1/plans
を実行する」ということです。
(1) パラメーター
上記GETメソッドを実行するときに、パラメーターを設定できます。
設定できる主なパラメーターは以下です。
- クエリパラメーター
- リクエストボディ
- パスパラメーター
(1.1) クエリパラメーター
APIでよく見られるのが、このクエリパラメーターだと思います。URLの?
のあとに見られるのがクエリパラメーターです。
サンプルコード
openapi: 3.0.0
info:
version: 1.0.0
title: Training Menu API
description: A simple menu for exercise
servers:
- url: http://localhost/training/v1
paths:
/plans:
get:
description: Return a list of training plans
#---ここから追加---
parameters:
- name: limit
in: query
description: Limit the number of plans on a page
schema:
type: integer
- name: offset
in: query
description: Specifies the page number of the plans to be displayed
schema:
type: integer
#---ここまで追加---
各パラメーターについて説明します。
パラメーター | 説明 |
---|---|
parameters |
リクエストパラメーターを記述するオブジェクト |
name |
パラメーターの名前。ここではlimit 、offset というパラメーターを用いている。 |
in |
パラメーターの種類。ここではquery (クエリパラメーター)を用いている。 |
description |
パラメーターの説明。 |
schema |
パラメーター構造を記述するオブジェクト。 |
type |
パラメーターの型の説明。ここではinteger 型を用いている。 |
ここまででわかることは、「クライアントはトレーニングプラン一覧に対し、1ページあたり10項目、全3ページを取得するために、GET http://localhost/training/v1/plans?limit=10&offset=3
を実行する。」ということです。
(1.2) リクエストボディ
POST
、PUT
、PATCH
リクエストの場合、リクエストボディを含むことが多いです。
リクエストボディは、requestBody
オブジェクトによって定義されます。
サンプルコード
openapi: 3.0.0
info:
version: 1.0.0
title: Training Menu API
description: A simple menu for exercise
servers:
- url: http://localhost/training/v1
paths:
/plans:
get:
description: Return a list of training plans
parameters:
- name: limit
in: query
description: Limit the number of plans on a page
schema:
type: integer
- name: offset
in: query
description: Specifies the page number of the plans to be displayed
schema:
type: integer
#---ここから追加---
post:
description: Register a new plan
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- plan_id
properties:
plan_id:
type: integer
planner_name:
type: string
plan_name:
type: string
duration:
type: integer
difficulty:
type: integer
#---ここまで追加---
各パラメーター/値について説明します。
パラメーター/値 | 説明 |
---|---|
requestBody |
リクエストボディを中身を設定するオブジェクト。 |
content |
リクエストボディの内容を示すオブジェクト。 |
application/json |
リクエストボディの構成がJSONであることを示す。 |
ここまででわかることは、「クライアントはトレーニングプラン一覧に対し、1ページあたり10項目、全3ページを取得するために、GET http://localhost/training/v1/plans?limit=10&offset=3
を実行する。また、plan_id
を必須パラメーターとして、planner_name
、plan_name
、duration
、difficulty
を選択することで新しいトレーニングプランを登録できる」ということです。
(1.3) パスパラメーター
パスパラメーターは、クライアントが操作しているデータの特定のコンポーネントを分離するために使われます。
パスパラメーターは必ずparameters
のところで定義されます。
サンプルコード
openapi: 3.0.0
info:
version: 1.0.0
title: Training Menu API
description: A simple menu for exercise
servers:
- url: http://localhost/training/v1
paths:
/plans:
get:
description: Return a list of training plans
parameters:
- name: limit
in: query
description: Limit the number of plans on a page
schema:
type: integer
- name: offset
in: query
description: Specifies the page number of the plans to be displayed
schema:
type: integer
post:
description: Register a new plan
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- plan_id
properties:
plan_id:
type: integer
planner_name:
type: string
plan_name:
type: string
duration:
type: integer
difficulty:
type: integer
#---ここから追加---
/plans/{planner_name}:
get:
description: Get information about the plan registered by the described planner
parameters:
- name: planner_name
in: path
required: true
schema:
type: string
#---ここまで追加---
ここまででわかることは、「クライアントはトレーニングプラン一覧に対し、1ページあたり10項目、全3ページを取得するために、GET http://localhost/training/v1/plans?limit=10&offset=3
を実行する。また、plan_id
を必須パラメーターとして、planner_name
、plan_name
、duration
、difficulty
を選択することで新しいトレーニングプランを登録できる。さらに、特定のplanner_name
をパスパラメーターに設定することができる(設定してリクエストを送信した後のレスポンスをどうするかは後述)。」ということです。
(2) レスポンス
各メソッドに対してレスポンスを返すのが、このレスポンスセクションです。
どのレスポンスも、最低1つ以上のHTTPステータスコードを記載する必要があります。ステータスコードを200
にすれば正常
、400
にすれば異常
としておけばよいでしょう。
レスポンスを記載したサンプルコードを掲載します。
サンプルコード
openapi: 3.0.0
info:
version: 1.0.0
title: Training Menu API
description: A simple menu for exercise
servers:
- url: http://localhost/training/v1
paths:
/plans:
get:
description: Return a list of training plans
parameters:
- name: limit
in: query
description: Limit the number of plans on a page
schema:
type: integer
- name: offset
in: query
description: Specifies the page number of the plans to be displayed
schema:
type: integer
#---ここから追加---
responses:
'200':
description: Successfully returned a list of training plans
content:
application/json:
schema:
type: array
items:
type: object
required:
- plan_id
properties:
plan_id:
type: integer
plan_name:
type: string
planner_name:
type: string
duration:
type: integer
difficulty:
type: integer
'400':
description: Invalid request
content:
application/json:
schema:
type: object
properties:
message:
type: string
#---ここまで追加---
post:
description: Register a new plan
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- plan_id
properties:
plan_id:
type: integer
planner_name:
type: string
plan_name:
type: string
duration:
type: integer
difficulty:
type: integer
#---ここから追加---
responses:
'200':
description: Successfully returned a list of training plans
'400':
description: Invalid request
content:
application/json:
schema:
type: object
properties:
message:
type: string
#---ここまで追加---
/plans/{planner_name}:
get:
description: Get information about the plan registered by the described planner
parameters:
- name: planner_name
in: path
required: true
schema:
type: string
#---ここから追加---
responses:
'200':
description: Successfully returned a list of training plans
content:
application/json:
schema:
type: array
items:
type: object
required:
- plan_id
properties:
plan_id:
type: integer
plan_name:
type: string
planner_name:
type: string
duration:
type: integer
difficulty:
type: integer
'400':
description: Invalid request
content:
application/json:
schema:
type: object
properties:
message:
type: string
#---ここまで追加---
ここまででわかることは、「クライアントはトレーニングプラン一覧に対し、1ページあたり10項目、全3ページを取得するために、GET http://localhost/training/v1/plans?limit=10&offset=3
を実行する。また、plan_id
を必須パラメーターとして、planner_name
、plan_name
、duration
、difficulty
を選択することで新しいトレーニングプランを登録できる。さらに、特定のplanner_name
をパスパラメーターに設定することで、そのplanner_name
に紐づいたトレーニングプランを取得できる。」ということです。
2.2.3. コンポーネント
上記に記載したサンプルYAMLを見ると、同じ用語がたくさん含まれているのがわかります(例:plan_name
、duration
など)。これらを何度も書くのはよくないです。情報は1箇所にまとまっているべきです。それを解決するのが、コンポーネントセクションです。
というわけで、ここではそれらの用語を再利用していくことを説明します。。
コンポーネントでは、以下のような型を定義できます。
- スキーマ
- パラメーター
- リクエストボディ
- レスポンス
- レスポンスヘッダ
- 例
- リンク
- コールバック
チュートリアルでは、スキーマ、パラメーターとレスポンスが掲載されていますので、今回もそれらを説明します。
(1) スキーマ
schema
では、全く同じ構造体をグループにまとめることができます。
例えば、サンプルYAMLでは以下の部分が全く同じなので、まとめることができます。
type: object
required:
- plan_id
properties:
plan_id:
type: integer
plan_name:
type: string
planner_name:
type: string
duration:
type: integer
difficulty:
type: integer
これらをcomponents
にしてまとめましょう。
まとめた結果、サンプルYAMLは以下のようになります。
openapi: 3.0.0
info:
version: 1.0.0
title: Training Menu API
description: A simple menu for exercise
servers:
- url: http://localhost/training/v1
paths:
/plans:
get:
description: Return a list of training plans
parameters:
- name: limit
in: query
description: Limit the number of plans on a page
schema:
type: integer
- name: offset
in: query
description: Specifies the page number of the plans to be displayed
schema:
type: integer
responses:
'200':
description: Successfully returned a list of training plans
content:
application/json:
schema:
type: array
items:
#---ここから変更---
$ref: '#/components/schemas/plan'
#---ここまで変更---
'400':
description: Invalid request
content:
application/json:
schema:
type: object
properties:
message:
type: string
post:
description: Register a new plan
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- plan_id
properties:
plan_id:
type: integer
planner_name:
type: string
plan_name:
type: string
duration:
type: integer
difficulty:
type: integer
responses:
'200':
description: Successfully returned a list of training plans
'400':
description: Invalid request
content:
application/json:
schema:
type: object
properties:
message:
type: string
/plans/{planner_name}:
get:
description: Get information about the plan registered by the described planner
parameters:
- name: planner_name
in: path
required: true
schema:
type: string
responses:
'200':
description: Successfully returned a list of training plans
content:
application/json:
schema:
type: array
items:
#---ここから変更---
$ref: '#/components/schemas/plan'
#---ここまで変更---
'400':
description: Invalid request
content:
application/json:
schema:
type: object
properties:
message:
type: string
#---ここから変更---
components:
schemas:
plan:
type: object
required:
- plan_id
properties:
plan_id:
type: integer
plan_name:
type: string
planner_name:
type: string
duration:
type: integer
difficulty:
type: integer
#---ここまで変更---
行数が短くなるのはもちろんですが、同じスキーマを使った新しくエンドポイントを追加するのも手短にできるようになります。
(2) パラメーターとレスポンス
他にも、同じパラメーターやレスポンスを一部まとめてみましょう。
openapi: 3.0.0
info:
version: 1.0.0
title: Training Menu API
description: A simple menu for exercise
servers:
- url: http://localhost/training/v1
paths:
/plans:
get:
description: Return a list of training plans
parameters:
- $ref: '#/components/parameters/PageLimit'
- $ref: '#/components/parameters/PageOffset'
responses:
'200':
description: Successfully returned a list of training plans
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/plan'
'400':
#---ここから変更---
$ref: '#/components/responses/400Error'
#---ここまで変更---
post:
description: Register a new plan
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- plan_id
properties:
plan_id:
type: integer
planner_name:
type: string
plan_name:
type: string
duration:
type: integer
difficulty:
type: integer
responses:
'200':
description: Successfully returned a list of training plans
'400':
#---ここから変更---
$ref: '#/components/responses/400Error'
#---ここまで変更---
/plans/{planner_name}:
get:
description: Get information about the plan registered by the described planner
parameters:
- name: planner_name
in: path
required: true
schema:
type: string
responses:
'200':
description: Successfully returned a list of training plans
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/plan'
'400':
#---ここから変更---
$ref: '#/components/responses/400Error'
#---ここまで変更---
components:
schemas:
plan:
type: object
required:
- plan_id
properties:
plan_id:
type: integer
plan_name:
type: string
planner_name:
type: string
duration:
type: integer
difficulty:
type: integer
#---ここから変更---
parameters:
PageLimit:
name: limit
in: query
description: Limit the number of plans on a page
schema:
type: integer
PageOffset:
name: offset
in: query
description: Specifies the page number of the plans to be displayed
schema:
type: integer
responses:
400Error:
description: Invalid request
content:
application/json:
schema:
type: object
properties:
message:
type: string
#---ここまで変更---
2.3. まとめ
これでREST APIの仕様書が作成できました。
このチュートリアルでやった流れは、
- メタ情報を書く
- パス情報を書く
- コンポーネントにまとめて整形する
です。