Swaggerのファイル分割を考える
✅ 目的
Swagger で OpenAPI 仕様(OAS)を定義したいです。
1ファイルで定義するとあっという間に膨大な記述量になり、メンテナンスが難しくなりそうです。
OpenAPI の仕様を元に、メンテナンス性の高い Swagger のファイル分割を考えることがこの記事の目的です。
✅ 対象読者
- Swagger に入門したい人
- どうやってファイル分割すれば良いか悩んでいる人
この記事では、以下の記事でまとめたことを前提に執筆します。
Swagger のファイル分割を考えるには、OpenAPI の仕様を理解していることが前提条件です。
✅ 結論
以下のような構成になりました。
説明 | |||
---|---|---|---|
openapi | - | - | openapi を定義するルートディレクトリ |
- | openapi.yml | - | OAS を定義するルートファイル |
- | paths | 各エンドポイントの定義を格納 | |
- | - | [リソース名] | リソース単位でエンドポイントの定義ファイルを格納 |
- | schemas | components の schema の定義を格納 |
公開されている Swagger Editor を元に分割したファイルツリーを以下に記載します。
pet
のリソースに注目して、詳細を解説します。
openapi/
├── openapi.yml
├── paths
│ ├── pet
│ │ ├── find-by-status.yml
│ │ ├── find-by-tags.yml
│ │ ├── index.yml
│ │ ├── pet-id.yml
│ │ └── upload-image.yml
│ ├── store
│ │ ├── inventory.yml
│ │ ├── order-id.yml
│ │ └── order.yml
│ └── user
│ ├── create-with-list.yml
│ ├── index.yml
│ ├── login.yml
│ ├── logout.yml
│ └── username.yml
└── schemas
├── address.yml
├── api-response.yml
├── category.yml
├── customer.yml
├── order.yml
├── pet.yml
├── tag.yml
└── user.yml
✅ OAS 定義
ルートとなる OpenAPI ドキュメントです。
公式ドキュメントに従ってファイル名はopenapi
とします。
ポイントはpaths
とcomponents
の2箇所です。
それぞれ、$ref
キーワードで外部ファイルを参照しています。
相対パスで参照します。
paths:
/pet:
$ref: "paths/pet/index.yml"
/pet/findByStatus:
$ref: "paths/pet/find-by-status.yml"
components:
schemas:
Address:
$ref: "schemas/address.yml"
ApiResponse:
$ref: "schemas/api-response.yml"
Category:
$ref: "schemas/category.yml"
✅ path 定義
ペットを登録・更新するエンドポイントです。
ID でペットを取得する際のレスポンスは、ペットスキーマ
ペット登録のリクエストボディ・レスポンスともに、コンポーネント化されたペットスキーマを$ref
で参照しています。
コンポーネントを参照することで、「ペットスキーマにプロパティを追加する」、などの変更をする場合、スキーマを定義している1つのファイルを変更するだけで対応できます。
スキーマ定義は後述します。
post:
tags:
- pet
summary: Add a new pet to the store
description: Add a new pet to the store
operationId: addPet
requestBody:
description: Create a new pet in the store
content:
application/json:
schema:
$ref: "../../openapi.yml#/components/schemas/Pet"
required: true
responses:
"200":
description: Successful operation
content:
application/json:
schema:
$ref: "../../openapi.yml#/components/schemas/Pet"
✅ schema 定義
ペットスキーマの定義ファイルです。
プロパティの定義は、別のスキーマ定義を$ref
キーワードで参照可能です。
相対パスで参照します。
tags:
type: array
items:
$ref: "tag.yml"
✅ 【余談】components 参照 vs 外部ファイル直接参照
この記事のサンプルコードでは、openapi.yml
で定義した components
を参照しています。
ファイル名の後に#
を記述して各フィールドにアクセスします。
responses:
"200":
description: Successful operation
content:
application/json:
schema:
$ref: "../../openapi.yml#/components/schemas/Pet"
components
を参照するのではなく、次のように外部ファイルを直接参照できます。
responses:
"200":
description: Successful operation
content:
application/json:
schema:
- $ref: "../../openapi.yml#/components/schemas/Pet"
+ $ref: "../../schemas/pet.yml"
執筆時点でどちらの記述が優れているか判断つきませんでした。
OAS を GUI で定義する Spotlight Studio が自動生成した OAS を確認すると、外部ファイルではなく、components を参照していたので、そちらに合わせています。
✅ まとめ
-
paths
とschemas
からファイル分割を考える - 外部ファイルは相対パスで参照するので、ディレクトリ構成を考えるときは注意する
この記事のサンプルコードは以下のリポジトリで公開しています
テンプレート用に最小サンプルのブランチを用意しました。
✅ 感想
最低限のファイル分割を考えることができました。
過度な分割やコンポーネント化は慎重になったほうが良さそうです。
リクエスト・レスポンス定義のコンポーネント化は必要かもしれません。
実践して知見が溜まったり、周りのエンジニア仲間と議論して理解が深まったら、都度この記事を更新していく予定です。
Discussion