OpenAPI Specification ざっくり説明
はじめに
次のリンクにある OpenAPI Specification (OAS) の内容を「ざっくり説明」として書き出しました。記述例など自分自身が後で理解しやすいように適当に変えています。
OpenAPIのもっと詳細な仕様はこちらのOpenAPI Specification v3.1.0を参照ください。
OpenAPIドキュメントの構造
ドキュメントの文法
YAMLかJSONで書く。
JSON:
{
"anObject": {
"aNumber": 42,
"aString": "This is a string",
"aBoolean": true,
"nothing": null,
"arrayOfNumbers": [
1,
2,
3
]
}
}
YAML:
# コメントが書ける。
anObject:
aNumber: 42
aString: This is a string
aBoolean: true
nothing: null
arrayOfNumbers:
- 1
- 2
- 3
複数のファイルに分割も可能。
必要最小限のドキュメント
ドキュメントのルートオブジェクトは OpenAPI Object。openapi
とinfo
の2つのフィールドが必須。あと、paths
、components
とwebhooks
のどれか一つが必要。
-
openapi
(string): OASのバージョン。 -
info
(Info Object): APIについての全般的な情報。-
title
(string): -
version
(strng): APIドキュメントのバージョン。
-
-
paths
(Paths Object): APIのパラメータやレスポンスを含むエンドポイントについての定義。
以下は最小限のドキュメント定義例。
openapi: 3.1.0
info:
title: 最小限のOpenAPIドキュメント
version: 0.0.1
paths: {} # エンドポイント定義なし
APIエンドポイント
エンドポイント一覧
OASでは、APIエンドポイント(オペレーションやルートとも呼ばれる)は Paths と呼ばれる。ルートのOpenAPI Object 直下にあるpaths
(Paths Object)はAPIが提供する全オペレーションが含まれる。
paths
の全てのフィールドは一つのAPIエンドポイントを定義するpath
(PathItemObject)となる。エンドポイントの名前は一意とする。
パスはスラッシュ /
始まりとする必要があり、サーバーURLと結合してエンドポイントのURLになる。
Path Item Object
Path Item Object は、パスに対するget
、put
やpost
といったHTTPオペレーションを Operation Object でそれぞれ定義する。
summary
やdescription
で全てのHTTPオペレーションに共通する事項について記載できる。
paths:
/board:
get:
・・・
put:
・・・
Operation Object
Operation Object では基本的に、HTTPオペレーションのリクエストパラメーターやペイロード、レスポンスを定義する。
paths:
/board:
get:
summary: ボード情報の取得
description: 現在のボード状態と勝者を取得する。
parameters:
・・・
responses:
・・・
Responses Object
Responses Object では、リクエストに対するサーバーのレスポンスを定義する。それぞれのフィールド名は引用符で囲まれたHTTPレスポンスコードで示し、レスポンスの内容は Response Object で定義する。
paths:
/board:
get:
responses:
"200":
・・・
"404":
・・・
Response Object
Response Object は、このHTTPオペレーションにおけるレスポンスの説明を記載するdescription
を必須のフィールドとして含む。このフィールドで一般的なHTTPレスポンスコードの意味に加えてAPI
固有の説明を記載できる。
最も重要なフィールドはcontent
フィールドで、そのレスポンスで返却できる内容を定義する。
paths:
/board:
get:
responses:
"200":
description: 処理が全て成功した場合のレスポンス。
content:
・・・
メッセージ本文の内容
Response Object のcontent
フィールドでレスポンスの内容を定義するが、リクエストのペイロードとしても使う。
content
フィールド
content
フィールドは、Response Object と Request Body Object で定義するフィールド。
これは、RFC6838のメディアタイプ(MIMEタイプ)と Media Type Object のマップになっている。
これは、メディアタイプによって異なる内容を返すように定義できる。メディアタイプにはワイルドカードの指定が可能。この場合、より具体的に指定されているメディアタイプの内容が優先される。
content:
application/json:
・・・
text/html:
・・・
text/*:
・・・
Media Type Object
Media Type Object は、レスポンスやリクエストボディ内容の構造を定義する。また、モックとして利用できるように具体例も示すことができる。
content:
application/json:
schema:
・・・
Schema Object
Schema Objectは、プリミティブ型(integer、stringなど)、配列やオブジェクトなどtype
フィールドの指定に応じたデータ型を定義する。
type
フィールドにはnumber
、integer
、string
、boolean
、array
およびobject
を指定できる。指定した型に応じ、更にデータ形式を指定するためのフィールドが利用できる。
integer
型はminimum
とmaximum
で値の範囲を制限できる。
content:
application/json:
schema:
type: integer
minimum: 1
maximum: 100
string
型は文字列長をminLength
とmaxLength
で制限できる。
また、型に関係なく指定できる値のセットをenum
配列を用いて制限できる。
content:
application/json:
schema:
type: string
enum:
- Alice
- Bob
- Carl
array
型は、items
フィールドが必須となっていてSchema Objectで配列の要素について型を定義する。更に、minItems
とmaxItems
で配列サイズを制限できる。
content:
application/json:
schema:
type: array
minItems: 1
maxItems: 10
items:
type: integer
object
型は、properties
フィールドにオブジェクトのプロパティを定義する。このフィールドは、プロパティ名とSchema Objectのマップ配列となる。
content:
application/json:
schema:
type: object
properties:
productName:
type: string
productPrice:
type: number
オペレーションのパラメータとメッセージペイロード
OpenAPIでは入力データとして パラメータ と リクエストボディ(メッセージペイロード) の2通りの方法を定義できる。通常、パラメータはリソースの識別に使い、メッセージペイロードはリソースの内容を提供する。
Parameter Object
Path Item Object と Operation Object のparameters
フィールドは、Parameter Object を要素とする配列となっている。Path Item Object の定義は、そのパスの全てのオペレーションで共有される。オペレーション単位でオーバーライドできるが、削除はできない。
各 Parameter Object では、次の必須フィールドを定義する。
-
in
(string): パラメータが使われるロケーション。 -
name
(string): パラメーターの名前。大文字と小文字を区別し、ロケーション単位で一意とする。
任意フィールドとして次のものを含む。
-
description
(string): 使用例などを含むドキュメンテーション。 -
required
(boolean): このパラメータが必須かどうかを示す。デフォルトはfalse
。
以降で示す追加フィールドで、パラメータの型、形式やシリアル化を指定できる。
パラメータ ロケーション
パラメータは、in
フィールドで指定できるいろんなロケーションで使用できる。主なものを次に示す。
-
path
: このパラメータがオペレーションのパス(URL)の一部であることを示す。パラメータの名前はテンプレート式として中カッコ{}
でパスに定義されている必要がある。
paths:
/users/{id}:
get:
parameters:
- name: id
in: path
required: true
注意: パスでパラメータを使う場合、required
フィールドをtrue
で定義する必要がある。
-
query
: パラメータは、オペレーションURLのクエリー文字列部分に追加される。
paths:
/users:
get:
parameters:
- name: id
in: query
この場合のURLは、/users?id=1234
のようになる。
-
header
: パラメータはリクエストの一部として、カスタムHTTPヘッダーとして送信される。ヘッダーの名前は大文字と小文字を区別しない。
パラメータの型
ほとんどの場合、パラメータの型はschema
フィールドで Schema Object を使って指定される。Schema Object はプリミティブ型や複合型(配列やオブジェクトなど)を定義でき、更に追加の制限を定義できる。
parameters:
- name: id
in: query
schema:
type: integer
minimum: 1
maximum: 100
もっと高度なシナリオで、content
フィールドを代わりに使える。これは、メディアタイプから Media Type Object への単一エントリーマップとして定義する。
注意: 正確には、schema
かcontent
のいずれか一つを定義する必要があり、同時に定義することはできない。
パラメータのシリアル化制御
style
フィールドは、どのようにパラメータがシリアル化されるかを定義し、シリアル化の内容はパラメータの型に依存する。
style
フィールドの主なものsimple
、form
、label
およびmatrix
について以降に示す。
-
プリミティブ型: 名前が
id
で値が 1234 の整数(integer)型パラメータの場合
style: | simple |
form |
label |
matrix |
---|---|---|---|---|
1234 |
id=1234 |
.1234 |
;id=1234 |
-
配列型: 名前が
ids
で値が 1、2 および 3 の整数(integer)を含む配列型パラメータの場合
explode
フィールドは、配列の要素を個別のパラメータとして分割するかを指定できる。
style: | simple |
form |
label |
matrix |
---|---|---|---|---|
explode=false を指定 |
1,2,3 |
ids=1,2,3 |
.1.2.3 |
;ids=1,2,3 |
explode=true を指定 |
1,2,3 |
ids=1&ids=2&ids=3 |
.1.2.3 |
;ids=1;ids=2;ids=3 |
-
オブジェクト型: 名前が
color
で、値が 1、2 および 3 の整数(integer)フィールド R、G および B を含むオブジェクト型パラメータの場合
explode
フィールドは、フィールドを個別のパラメータとして分割するかを指定できる。
style: | simple |
form |
label |
matrix |
---|---|---|---|---|
explode=false を指定 |
1,2,3 |
ids=1,2,3 |
.1.2.3 |
;ids=1,2,3 |
explode=true を指定 |
1,2,3 |
ids=1&ids=2&ids=3 |
.1.2.3 |
;ids=1;ids=2;ids=3 |
シリアル化の詳細は、Parameter Object の仕様ページを参照。
Request Body Object
データベースのレコードを更新する際、一般的にはパラメータでレコードを識別し、メッセージ本文で更新内容となる新しいコンテンツを指定する。
リクエストのメッセージ本文は、Operation Object のrequestBody
フィールドである Request Body Object で指定する。
paths:
/board:
put:
requestBody:
・・・
Request Body Object の唯一の必須フィールドはcontent
で、メッセージ本文の内容の説明したもの。
Request Body Object は、メッセージ本文の簡単な説明を記述するdescription
フィールドと、メッセージ本文を必須とするかを示すrequired
フィールドを持つ。
定義の再利用
OpenAPI ドキュメントでは、定義を再利用して冗長性を取り除く仕組みがある。
Components Object
ルートであるOpenAPI Object直下のcomponents
フィールドであるComponents Objectは、ドキュメントの他の箇所から再利用できるオブジェクトの定義が含まれている。
OpenAPI ドキュメントに定義するほとんどのオブジェクトはコンポーネントへの参照に置き換えることができ、ドキュメントサイズとメンテナンスのコストを大幅に減らしてくれる。
参照できるオブジェクトはschemas
、responses
やparameters
など Components Object のフィールドとなっているものだけ。
Components Object の各フィールドは、再利用のためのオブジェクトにマッピングされるコンポーネント名となる。これらのオブジェクトの種類は、親フィールドに一致しないといけない。例えば、schemas
フィールドのオブジェクトは Schema Objects でなければいけない。
次の例では二つのオブジェクトを定義している。
-
coordinate
はスキーマコンポーネントで、Schema Object が期待される箇所で参照できる。 -
rowParam
はパラメータコンポーネントで、Parameter Object が期待される箇所で参照できる。
components:
schemas:
coordinate:
type: integer
minimum: 1
maximum: 3
parameters:
rowParam:
name: row
in: path
required: true
Reference Object
Components Objectで対応している型のOpenAPIオブジェクトは、任意のコンポーネントを指す Reference Object で置き換えできる。
Reference Object は JSON Reference で表し、$ref
フィールドに参照オブジェクトを指すURIを指定しただけのオブジェクト。
$ref: 'https://gigantic-server.com/schemas/Monster/schema.yaml'
URIは絶対または相対で指定で、フラグメント識別子を含めることができる。
$ref: './another_file.yaml#rowParam'
次の例では、同じドキュメント内の定義を参照している。
パラメータコンポーネント(rowParam
とcolumnParam
パラメータ)から同じスキーマコンポーネント(coordinate
スキーマ)を参照している。また、/board/{row}/{column}
パスから2つのパラメータを参照している。
components:
schemas:
coordinate:
type: integer
minimum: 1
maximum: 3
parameters:
rowParam:
name: row
in: path
required: true
schema:
$ref: "#/components/schemas/coordinate"
columnParam:
name: column
in: path
required: true
schema:
$ref: "#/components/schemas/coordinate"
paths:
/board/{row}/{column}:
parameters:
- $ref: "#/components/parameters/rowParam"
- $ref: "#/components/parameters/columnParam"
ドキュメントと具体例の記述
OpenAPIドキュメントはコンピュータで処理するための記述だけでなく、開発者が読むためのドキュメントも記述できる。
ドキュメンテーションフィールド
OpenAPI仕様のほとんどのオブジェクトは、開発者への追加情報を提供するためdescription
フィールドを持っている。
例えば、パラメータの目的や仕様、他のパラメータとの相関などを記載できる。
paths:
/audio/volume:
put:
requestBody:
required: true
content:
application/json:
schema:
type: integer
minimum: 0
maximum: 10
description:
オーディオ主音量を指定する。
0 は音量ゼロを指定する(ミュート状態)。 10 が最大音量。
0 を指定した場合、アラーム音量には影響しない。
・・・
Path Ietm Object 、Operation Object および Example Object は説明が長くなりがちなため、要約を記述できるsummary
フィールドを持っている。
YAMLにおける長文説明の記述
JSONの場合、文字列は引用符で囲まれているので開始と終了が明確。YAMLの場合、複数行の文字列だと少し分かりづらい。
上記のYAML記載例のような長い説明では、インデントが小さい行が出てきた時点で終了と判断されるので、行の先頭にあるスペースが重要になる。この例は プレーンモード を使っていて特別な構文を使わないので記載が簡単だが、文字列にコロン:
やハッシュ#
といった文字を含む場合にYAMLパーサーを混乱させてしまうため、引用符で囲って回避してあげないといけない。
description: "Beware of lines containing colons and hashes like this: #"
改行位置を正確にコントロールしたい場合には更に2つのモードとして リテラルモード と 折りたたみモード が在り、説明の先頭行のインジケーター文字だけで有効になる。リテラルモード と 折りたたみモード では引用符は不要。
-
リテラルモード (パイプ
|
で示す。): YAMLファイルのソースにある改行は出力でそのまま維持される。
YAML source:
description: |
This is a string
in multiple lines.
And an extra one.
Output:
This is a string
in multiple lines.
And an extra one.
-
折りたたみモード (大なり記号
>
で示す。): 改行は削除され、出力は一つの文字列になる。但し、空行は改行になる。
YAML source:
description: >
This is a string
in multiple lines.
And an extra one.
Output:
This is a string in multiple lines.
And an extra one.
CommonMark構文
description
フィールドでは、CommonMark 0.27 を使ってリッチなテキスト書式指定が可能。CommonMark構文の日本語訳
Example Object
一部のOpenAPIオブジェクトは、具体例をdescription
フィールドに埋め込む代わりに明示的に表記でき、ツールで自動的に処理できるようになっている。
example
フィールドでは一つの具体例を、examples
フィールドで複数の具体例を示すことができ、これによって次のことが可能になる。
- ドキュメント中で具体例を特別にレンダリングする。
- Example Object をモックサーバーの戻り値として利用する。
各オブジェクトで、example
フィールドまたはexamples
フィールドのどちらかを記述できる。
example
フィールド(Parameter Object、 Media Type Object および Schema Object のフィールド)は、その親オブジェクトの形式に一致しないといけない。
schema:
coordinate:
type: integer
minimum: 1
maximum: 3
example: 1
examples
フィールド(Parameter Object および Media Type Object のフィールド)は、具体例の名前と Example Object のマップになっている。Example Object には実際のコード(value
フィールド内またはexternalValue
フィールドの外部参照)と、その説明のためのsumamry
およびdescription
フィールドがある。
APIサーバー
定義したAPIにアクセス可能なサーバーを定義することができ、複数のURLや可変部分が含まれる。
Server Object
Server Object はAPIが提供されるベースURLを設定する。ルートの OpenAPI Object 、Path Item Object および Operation Object のservers
配列フィールドとして定義できる。
servers
配列フィールドの各要素は Server Object になっていて、サーバーのベースURLをurl
フィールドに設定する。description
フィールドでサーバーの説明を記載することもできる。
servers:
- url: https://dev.server.com/v1
description: 開発環境のサーバー
- url: https://test.server.com/v1
description: テスト環境のサーバー
- url: https://www.server.com/v1
description: 本番環境のサーバー
このベースURLに Paths Object で指定されている各APIエンドポイントをくっ付けることで完全なエンドポインURLになる。例えば、
servers:
- url: https://server.com/v1
paths:
/users:
get:
の場合、https://server.com/v1/users
のようにGETリクエストを実行してアクセスできることになる。
あるオペレーションに対して OpenAPI Object 、Path Item Object や Operation Object など複数のservers
配列フィールドで指定されている場合、いちばん低いレベルのものが適用される。例えば、
servers:
- url: https://server1.com
paths:
/users:
get:
servers:
- url: https://server2.com
の場合、/users
エンドポイントへのGETリクエストはhttps://server2.com
で提供されることになる。
ドキュメントにサーバーが定義されていない場合、全てのAPIエンドポイントはOpenAPIドキュメントが提供されているロケーションからの相対パスと想定することになる。
サーバー変数
サーバーURLには、中カッコ {}
で区切られた変数を含めることができる。
servers:
- url: https://{username}.server.com:{port}/{version}
これらの変数はvariables
フィールドで詳細を定義する必要がある。このフィールドは変数名と Server Variable Object のマップになっていて、サーバーURLに含まれている中カッコ内の変数名の一つに一致していないといけない。
Server Variable Object は次のフィールドを持っている。
-
default
(string): 必須フィールドで、変数の値が指定されない場合に適用される。 -
enum
(stringの配列): 変数の有効な値を配列で定義できる。このフィールドが定義されている場合、default
フィールドの値は定義されている配列値に含まれている必要がある。 -
description
(string): 変数についての説明を記載。
変数値は次のような方法で指定することができる。
- OpenAPIジェネレーターでの生成時に指定
- OpenAPIドキュメントからOpenAPIジェネレーターを使ってAPIクライアントやサーバースタブなどを生成する際のコマンドラインオプションとして指定できる。
- 例:
--server-variables
オプションによる指定
openapi-generator-cli generate --server-variables username=test,port=443,version=v99
- Swagger UIやIDEのプラグインなどツールによるAPI実行時に指定
- ビジュアルツールでは変数値を入力指定できるように対応されている。
- 例: Visual Sutdio Codeの拡張機能「OpenAPI (Swagger) Editor」の場合
おわりに
書きながら参考にOpenAPI Specification v3.1.0を読んでいて
- Security Scheme Object
- Discriminator Object
- XML Object
がちゃんとわからん...と感じましたので記事にして理解したいなと思っています。
Discussion
一番上のリンク (https://oai.github.io/Documentation/specification.html) が切れているようです。
切れる前のリンク先を見てないため間違っているかもしれませんが、おそらく現在はここに移動してます!(内容が同じことから判断しました) → https://learn.openapis.org/specification/
ご指摘ありがとうございます。いただいたリンクの内容で正解です!!
記事のリンク修正しました。