背景
2017/7にSwaggerはOpenAPI Specificationとして生まれ変わりました。
正確にはSwaggerの開発元(?)であるSMATRBEAR SoftwareがSwagger2.0をOpen API Initiativeに寄贈し、それを元にOpenAPI Specification(以下OAS) 3.0が作られました。
Swagger2.0と比較してOAS3.0では様々な拡張とリファクタリングが行われましたが、その中でParameter Objectについて記法がかなり拡張されたのでそれについて書きたいと思います。
そもそもSwagger(OAS)って何?
こちらの記事でも述べましたが、この時と多少変わっているので、 https://swagger.io/specification/ から引用します。
The OpenAPI Specification (OAS) defines a standard, language-agnostic interface to RESTful APIs which allows both humans and computers to discover and understand the capabilities of the service without access to source code, documentation, or through network traffic inspection. When properly defined, a consumer can understand and interact with the remote service with a minimal amount of implementation logic.
要するにはRESTfulAPIのインターフェース定義を記述するためのものです。
昨今では銀行がAPIを公開し始めていたりします。API利用者に対してAPIの使い方を説明する仕様書を提示することになると思いますが、その仕様書の書き方に一石を投じることになるでしょう。
従来は仕様書はExcelやWordや色々な文書として書かれていましたが、OASが整備されたことによって統一化されていくことが期待されます。
具体的にはYAMLもしくはJSONで記述します。こうした機械的に扱いやすい形式を採用することで、
- HTMLやPDF形式のドキュメントとして出力
- APIクライアントのソースコード生成
- API実装の雛形生成
などを自動化することが出来ます。
事実、SMARTBEARはSwagger Toolsというツール群を提供しています。
Parameter Object
Parameter Objectは下記のようなAPIエンドポイントの入力引数を表すオブジェクトです。
- GET /user/{username}
- GET /pet/findByStatus?status=Living
Parameterの場所(in)
一般的にはクエリーとしてパラメータを定義することが多いでしょうが、OASではin
フィールドで、
- query
- path
- header
- cookie
の4種類が指定できます。
尚、OAS3.0からリクエストボディはRequest Body ObjectとしてParameterとは別の概念になったため、in:body
と言う指定方法は廃止されました。
defaultの廃止
Swagger2.0まではdefaultとして、パラメータのデフォルト値を指定できましたが廃止されました。
schema
Swagger2.0まではschema定義できるのはin
がbody
の時(すなわちリクエストボディを定義するとき)だけでしたが、OAS3.0ではin
の種類によらずSchema定義が可能です。Schemaのtypeとしてobjectを指定することも可能で、つまりは単純な文字、配列だけでなく複雑な階層化されたJSONオブジェクトをクエリパラメータやヘッダとして指定することが可能になっています。
また、Swagger2.0まではParameterの型がstring,integer,booleanの場合には直接Parameter Objectにtypeを指定していたのですが廃止され、schema定義をする必要があります。
style
上記のschema.type
としてarrayやobjectが指定することができるようになったのとに伴いOAS3.0からParameterのシリアライズという概念が導入されました。
Describes how the parameter value will be serialized
シリアライズは端的に言うとJSON object
やJSON array
を文字列化することです。
これは、Swagger2.0ではcollectionFormatという指定でtypeがarrayのときのみでしたが、OAS3.0からはstyleに変更され、typeがobjectの場合の考慮もされるようにました。
しかし、その反面、どんなときにどのstyleが使用できると言うルールが複雑化しました。
JSONの文字列化ならstringifyすればいいじゃないかって? 私もそう思うのですが、単純にstringifyするとURLセーフではない文字列が含まれうるということでしょう。
(それにしてもパーセントエンコードすれば良いのではと思うのですが・・・)
explode
trueの場合、object, arrayを別個のパラメータに分割します。
これは例を見たほうが早いでしょう。
/hair:
parameters:
- name: color
in: query
schema:
type: object
style: form
{"R": 0, "G": 255, "B": 128}
この場合、explodeの値により以下のようになります。
explode | クエリ式 |
---|---|
false | /hair?color=R,0,G,255,B,128 |
true | /hair?R=0&G=255&B=255 |
この形式はstyleによって変わります。
style, explodeのまとめ
従来のcollectionFormatに代わって登場したstyleですが、
- inの種類によって使用可能なstyleに制約がある
- explodeとの組み合わせでシリアライズ形式が変る
- typeによってもシリアライズ形式が変る
ということでかなり仕様としては複雑になりました。
pathに指定可能なstyle
/path/to/{param}
の場合
style | explode | |
---|---|---|
matrix | false | /path/to/;color=R,100,G,200,B,150 |
true | /path/to/;R=100;G=200;B=150 | |
label | false | /path/to/.R.100.G.200.B.150 |
true | /path/to/.R=100.G=200.B=150 | |
simple | false | /path/to/R,100,G.200,B,150 |
true | /path/to/R=100,G=200,B=150 |
queryに指定可能なstyle
/path/to?param=
の場合
style | explode | |
---|---|---|
form | false | /path/to?param=R,100,G,200,B,150 |
true | /path/to?R=100&G=200&B=150 | |
spaceDelimited | false | /path/to?param=R%20100%20G%20200%20B%20150 |
pipeDelimited | false | /path/to?param=R¦100¦G¦200¦B¦150 |
deepObject | true | /path/to?color[R]=100&color[G]=200&color[B]=150 |
ここで戸惑うのはcollectionFormat=csv
相当のstyle=simple
が使用できなくなったことです。
headerに指定可能なstyle
style | explode | |
---|---|---|
simple | false | x-param: R,100,G.200,B,150 |
true | x-param: R=100,G=200,B=150 |
※explode=trueのとき自信なし
cookieに指定可能なstyle
style | explode | |
---|---|---|
form | false | cookie: param=R,100,G,200,B,150 |
true | cookie: R=100; G=200; B=150; |
※explode=trueのとき自信なし
まとめてみたものの
まだ仕様的に整合が取れていない気がする
https://swagger.io/specification/#styleValues によると
- spaceDelimited
- pipeDelimited
- simple
は type=array のみではないのか?
また、in=cookie, style=form, explode=true の場合は&ではなく;で区切るべきと思われる。
SwaggerUI側が未対応
Parameter Objectを細かく記述したとして、残念ながらSwagger UIがまだ対応していないためドキュメントには反映されません。