api
swagger

Swagger3.0(OpenAPI Specification 3.0)で強化されたParameter Object

More than 1 year has passed since last update.

背景

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定義できるのはinbodyの時(すなわちリクエストボディを定義するとき)だけでしたが、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 objectJSON arrayを文字列化することです。

これは、Swagger2.0ではcollectionFormatという指定でtypeがarrayのときのみでしたが、OAS3.0からはstyleに変更され、typeがobjectの場合の考慮もされるようにました。
しかし、その反面、どんなときにどのstyleが使用できると言うルールが複雑化しました。

JSONの文字列化ならstringifyすればいいじゃないかって? 私もそう思うのですが、単純にstringifyするとURLセーフではない文字列が含まれうるということでしょう。
(それにしてもパーセントエンコードすれば良いのではと思うのですが・・・)

explode

trueの場合、object, arrayを別個のパラメータに分割します。
これは例を見たほうが早いでしょう。

swagger定義
/hair:
  parameters:
    - name: color
      in: query
      schema:
        type: object
      style: form
colorの具体値令
{"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, exprodeのまとめ

従来の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

RFC6570

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がまだ対応していないためドキュメントには反映されません。