OpenAPI Spec 3.0でのSwagger Specの分割管理


概要

Swaggerの定義ファイルを分割して管理したいと思ったことはないですか。
とかく長くなりがちなあのファイル、探してみると分割した場合のサンプルは出てきます。
ただし、このサンプルは以下の二点が気になります

  • 最終的に multi-file-swagger を使って、ファイルをマージすることが前提なこと
  • ファイル形式がSwagger 2.0のものであること

できれば、以下のようなサンプルが欲しいです。

ないなら作るしかないのでサンプルを作ってみました

サンプル

コードサンプル: https://github.com/funa1g/multi-file-oas-example
SwaggerUIサンプル: https://funa1g.github.io/multi-file-oas-example/

Swaggerのデフォルトのサンプルである PetStore を元にしています。

ディレクトリ構成

  • APIの各パスごとにファイルを作成
  • コンポーネントは、各モデルごとにファイルを作成

以下のようなディレクトリ構成になります。

├── openapi.yml
├── components
│   ├── pet.yml
│   ├── pets.yml
│   └── error.yml
└── paths
    ├── pet.yml
    └── pets.yml

rootとなるopenapi.ymlは以下のようになります。

openapi.yml
openapi: "3.0.0"
info:
  version: 1.0.0
  title: Swagger Petstore
  license:
    name: MIT
servers:
  - url: http://petstore.swagger.io/v1
paths:
  /pets:
    $ref: './paths/pets.yml'
  /pets/{petId}:
    $ref: './paths/pet.yml'
components:
  schemas:
    Pet:
      $ref: './components/pet.yml'
    Pets:
      $ref: './components/pets.yml'
    Error:
      $ref: './components/error.yml'

Swagger2.0の場合は、paths以下、すなわちAPIのパス指定から全て別ファイルにしているケースなどが紹介されていました
OAS3.0でも、最終的にファイルをマージするならば、このやり方でも問題はありません。

ですが、公式のドキュメントでは、 $ref による参照は、どこでも使えるわけではなく、個別の要素に対して指定するものであるとしています
事実、paths 以下を別ファイルにして、さらにそこから別ファイルを参照してという形式では、SwaggerUIでは正しく表示がされませんでした。
ですので、今回のような形式に落ち着いています。

問題点

一つのファイルで表示する場合と違って、正しく表示されない部分があります。
以下のような問題が確認できます。

  • Modelが参照するModel名がおかしい
    • PetsというModelはPetのリストなんですが、Petsのリストかのように表示されています
  • 各APIが参照しているModelの名前が表示されない
    • パラメータはきちんと指定通り表示されますが、Modelの名前が出ません
    • そのため、どこが共通要素か確認しづらいです
  • エディタが複数ファイルによるプレビューをサポートしていない
    • VisualStudioCodeのSwaggerViewerはダメでした

パスの指定方法やファイルの分割箇所もいくつか試してみましたが、これでも現状が一番みやすそうという結論です

結論

  • ファイル分割しても、 multi-file-swagger を利用してマージが推奨
  • 分割したまま見るなら、パスやコンポーネントごとにファイルを作る。ただし表示の問題は目をつむる必要がある

厳密さが期待されるプロジェクトでは、やっぱり multi-file-swagger を利用するのがいいかなと思います。
小規模な開発なら今回のような方法を取るのもありって感じでしょうか。
より良い方法などご存知の方は、ぜひお教えください。