.../articles/

OpenAPIのスキーマを分割・構造化していく方法

ファイルが大きくなりがちなOpenAPIのスキーマの定義ファイルを分割・構造化して運用していく方法について書きました。

前の記事でOpenAPIのスキーマを中心に開発を進める方針についてに書きました。

OpenAPIやSwaggerのファイルを記述していくとよくあるつらい点は、内容に対してファイルが肥大化しやすいことだと思います。(エンドポイントはそんなにないのに数百行とか😇)

上記のファイルが大きくなるというつらみは結構深刻な問題だと考えているので、 $ref を使ってファイルを分割しつつスキーマを書いていく方針にしようかと思っています。

ただ、現状OpenAPIと連携できるツールでもファイルの参照を解釈できるものがあまりなさそうなので結局1つのファイルにしておくと使いやすいかなとも考えています。

ということで、ファイルを分割してスキーマを管理しつつ最終的に1つのスキーマとして結合する方法を試してみました。


ファイルを分割してスキーマを管理する

まずファイルを分割してスキーマを管理する方法について、例となるスキーマを作ってリポジトリにまとめてみたのでこれを参考に紹介していきます。

起点となるのは root.yml 、それ以外のファイルはOpenAPI Objectのネームスペースに従ってディレクトリをわけ各ファイルからは相対パスで情報を参照しています。

root.yml からはパス毎に定義したファイルを参照していきます。
/users に関する定義であれば ./paths/users.yml/users/{user_id} に関する定義であれば ./paths/users-by-id.yml に記述していきます。

# root.yml
paths:
  /users:
    $ref: ./paths/users.yml
  /users/{user_id}:
    $ref: ./paths/users-by-id.yml

パス以下はメソッド毎のパラメータやレスポンスについて記述されています。

# paths/users.yml
get:
  operationId: usersGet
  summary: get user list
  tags: [user]
  parameters:
    - $ref: ../components/parameters/page.yml
    - $ref: ../components/parameters/per_page.yml
  responses:
    200:
      description: ok
      content:
        application/json:
          schema:
            $ref: ../components/schemas/user_list.yml
post:
  operationId: usersPost
  summary: create new user
  tags: [user]
  requestBody:
    description: user information
    required: true
    content:
      application/json:
        schema:
          $ref: ../components/schemas/user_input.yml
  responses:
    201:
      description: created
      content:
        application/json:
          schema:
            $ref: ../components/schemas/user.yml

共通して使用するようなパラメータは components/parameters 以下で定義したファイルを参照し、リクエストボディやレスポンスで返すオブジェクトの情報は components/schemas 以下で定義したファイルを参照します。

このようにファイルが分割されていることで、スキーマを更新したい時に何処を追記または修正すればいいのかがわかりやすくなります。

スキーマを結合する

ここまで紹介したような方法であればスキーマは管理しやすくなりますが、最終的にはスキーマが1つのファイルになっていたほうがありがたいと思います。

そこでスキーマを結合するために openapi-generator を使います。

openapi-generator はスキーマをベースにしたクライアント向けのコードなどを生成できるのですが、コマンドで利用可能なgeneratorの種類を見てみると openapiopenapi-yaml というのがあります。(READMEには書いてない?)

DOCUMENTATION generators:
    - cwiki
    - dynamic-html
    - html
    - html2
    - openapi
    - openapi-yaml

このgeneratorをつかうことで root.yml をベースにファイルの参照を展開した状態のスキーマをJSONまたはYAMLで生成することができます。

# JSON形式で結合したスキーマを出力
$ openapi-generator generate -g openapi -i root.yml -o generated
# YAML形式で結合したスキーマを出力
$ openapi-generator generate -g openapi-yaml -i root.yml -o generated

これでスキーマの管理は分割したファイルで行いつつ、最終的に1つのスキーマとして出力することができるようになりました。
自分が見た限りではファイルの参照が正しく展開されているようです。


余談

OpenAPIToolsは公式ではない?

openapi-generator を公式のツールという感じで紹介している記事もあるのですが、
GitHubのorganizationを見てみると以下のように書いてあります。

NOTE: This organization is not affiliated with OpenAPI Initiative (OAI)

これをみると公式ではなさそうですが、開発は活発に行われているようですし同様のツールの中では比較的よく使われているようなのでとりあえずはこれを使っていこうかと思っています。

ファイルを分割するとスキーマを書くのがつらい?

Swagger Editorや各種エディタのプラグインを使うとスキーマを編集しながら検証してくれたり、キーを補完してくれるので編集するのが簡単になります。

しかし、ファイルを分割してしまうとそのファイル単独ではOpenAPIのスキーマとして成立しないのである程度スキーマの書き方がわかっていないと大変かもしれません。

openapi-generator で結合する段階では明らかに間違ったスキーマはわかりますが、それまでわからないのもつらいかなと思いました。

今はスキーマの変更のたびにgeneratorを実行しているので、スキーマの変更を検出してプレビューしながら編集できるようになるといいかもしれません。

  • 追記

分割したスキーマのファイルを検知して openapi-generator を実行するために chokidar を使ってみました。

以下のように watch というnpm scriptを実行するとスキーマ定義のYAMLファイルの変更を検知して結合したスキーマを生成してくれます。 openapi-generator, npm-run-all など必要なパッケージをインストールしてください。

{
  "scripts": {
    "validate-generated-schema": "openapi-generator validate -i generated/openapi/openapi.yaml",
    "run-generator": "openapi-generator generate -g openapi-yaml -i root.yml -o generated",
    "generate": "npm-run-all -s run-generator validate-generated-schema",
    "watch": "chokidar 'root.yml' '**/*.yml' -c 'yarn generate'"
  }
}

また、1つのファイルでスキーマを編集していく場合はStoplight Studioを使っていくのも良さそうです。

.../articles/

Articles

記事

AWS AmplifyにmonorepoのNext.js(App Router)をデプロイする

AWS AmplifyにmonorepoのNext.js(App Router)をデプロイする

monorepo管理しているNext.jsをAmplifyにデプロイしようとした際にいくつか躓く内容があったのでまとめておきます。

リモートワーク・オンライン会議でも、スムーズに制作を進めるために大切なこと[資料編]

リモートワーク・オンライン会議でも、スムーズに制作を進めるために大切なこと[資料編]

コロナ禍の影響により、リモートワークの導入をおこなっている制作会社も多く、実際に弊社でも導入しています。

売れるECサイトデザインを作るために。参考にしたいおしゃれな事例の探し方。

売れるECサイトデザインを作るために。参考にしたいおしゃれな事例の探し方。

売れるECサイトのデザインは、「この形式」という決まりはありません。ECサイトで売り上げを上げるなら、しっかりとしたコンセプトと、コンセプトを決定するまでのリサーチが必要です。

制作会社の考える、業務効率化ツールのおすすめ。個人でも使いやすいサービスなど。

制作会社の考える、業務効率化ツールのおすすめ。個人でも使いやすいサービスなど。

新型コロナウイルス感染拡大の影響で、リモートワークが主流になり、弊社でも週のほとんどは各自宅で作業をしています。

Figmaでデザインのコミット履歴を残せるプラグイン【Thought Recorder】をリリースしました

Figmaでデザインのコミット履歴を残せるプラグイン【Thought Recorder】をリリースしました

Figmaを利用するWebデザイナーの助けになれると嬉しいです。使い方は本記事をご覧ください。

ECの構築方法、おすすめのECサービス。

ECの構築方法、おすすめのECサービス。

ファッションや家電、スーパーの買い物でさえもECサイトを利用することが当たり前になりました。加えて新型コロナウイルスの影響もあり、弊社にも「どんなプラットフォームを利用したら良いか」「どれくらいコストがかかるのか」などECに関するさまざまなご相談を頂きます。

FastAPIのスキーマクラスをOpenAPIから生成する方法

FastAPIのスキーマクラスをOpenAPIから生成する方法

PythonでAPIを構築する要件があり、フレームワークに比較的モダンなFastAPIを採用しました。FastAPIはバックエンドの開発を行えば自動でOepnApi定義を生成する機能が備わっていますが、今回はこれを使わず、事前に用意したOepnApi定義からFastAPIで利用するスキーマクラスを生成する方法を紹介します。

Laravel 日本一解りやすい全文検索のマイグレーション記載方法解説

Laravel 日本一解りやすい全文検索のマイグレーション記載方法解説

Laravel + MySQLで全文検索を実装する

GiFT1号目新卒デザイナーの2021年振り返り

GiFT1号目新卒デザイナーの2021年振り返り

いつの間に、年末ですね。入社してもう、9ヶ月も立っていたようです。2021年の振り返りを記事にしました。

TimesclaeDBのデータ圧縮に関して

TimesclaeDBのデータ圧縮に関して

TimescaleDBはデータベース内の一部のテーブルを時系列データとして扱えるPostgreSQLの拡張です。PostgreSQLの機能拡張なので非常に手軽に導入できます。今回はこのTimesaceDBの圧縮について調べたので備忘録として書き綴りました。

すべての記事

お問い合わせ