OpenAPI ファイルを 分割 / 結合 する 方法

0 件のコメント

今回は「OpenAPI の ファイル を 分割/結合 する方法」についてまとめます。

OpenAPIは普通に記述しているとどうしても肥大化してしまいます。 なので、どこかのタイミングでファイル分割を検討することになります。 今回はその「ファイル分割/結合」の方法についてまとめました。

元にするOpenAPI

今回は OpenAPI でよく出てくる Swagger Petstore のAPIを利用してファイル分割、結合をやってみます。 Swagger PetstoreGitHub OAI / OpenAPI-Specification で取得できます。 以下に断面は記載しておきます(コードは閉じているので開くと確認できます)。

openapi: "3.0.0"
info:
  version: 1.0.0
  title: Swagger Petstore
  license:
    name: MIT
servers:
  - url: http://petstore.swagger.io/v1
paths:
  /pets:
    get:
      summary: List all pets
      operationId: listPets
      tags:
        - pets
      parameters:
        - name: limit
          in: query
          description: How many items to return at one time (max 100)
          required: false
          schema:
            type: integer
            format: int32
      responses:
        '200':
          description: A paged array of pets
          headers:
            x-next:
              description: A link to the next page of responses
              schema:
                type: string
          content:
            application/json:    
              schema:
                $ref: "#/components/schemas/Pets"
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      summary: Create a pet
      operationId: createPets
      tags:
        - pets
      responses:
        '201':
          description: Null response
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /pets/{petId}:
    get:
      summary: Info for a specific pet
      operationId: showPetById
      tags:
        - pets
      parameters:
        - name: petId
          in: path
          required: true
          description: The id of the pet to retrieve
          schema:
            type: string
      responses:
        '200':
          description: Expected response to a valid request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pet"
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
components:
  schemas:
    Pet:
      type: object
      required:
        - id
        - name
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
        tag:
          type: string
    Pets:
      type: array
      items:
        $ref: "#/components/schemas/Pet"
    Error:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: integer
          format: int32
        message:
          type: string

ファイル分割

ファイル分割でポイントになるのは $ref を用いたオブジェクト参照です。 その記述方法は HTML のハイパーリンクに似ています。 $ref の記述方法は以下のような2パターンを覚えておけばOKです。

  • 同一ファイル内の別オブジェクトを参照

    $ref: "#/components/schemas/Pet"

    "#"(ハッシュ) に続けてファイル内のオブジェクトパスを指定します。

  • 別ファイルのオブジェクトを参照

    $ref: "./schemas.yaml"

    現在のファイルから見た相対パスでファイル指定します。

では、前述の $ref オブジェクト参照 はどこでも使えるかというと…使える場所が限定されています。 どこで使えるかの詳細はリファレンスを参照になりますが…主要なものは以下の箇所になります。

  • paths/{path}
  • components/schemas
  • components/responses
  • components/parameters
  • components/examples
  • components/requestBodies
  • components/headers
  • components/securitySchemes

では、上記を参考にしながらさっそくファイル分割を行っていきましょう。

分割後のファイル構成は以下のようになります。 順にどのように記述するか見ていきましょう。

<ROOT>
│  openapi.yaml
│  
├─paths
│      pets.petid.yaml
│      pets.yaml
│      
└─schemas
        Error.yaml
        index.yaml
        Pet.yaml
        Pets.yaml

ファイル分割のポイントは $ref です。 $ref は指定したファイルからの相対パスで指定します。 ルートドキュメント ( openapi.yaml ) からのパスではない点に注意です。

/openapi.yaml

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.yaml"
  "/pets/{petId}":
    $ref: "./paths/pets.petid.yaml"
components:
  schemas:
    $ref: "./schemas/index.yaml"

できるだけ上位のオブジェクトで分割を行います。 paths 直下から分割しているブログも見かけたりしますが… 一応 OpenAPI 仕様的にはNGです。

/schemas/index.yaml

Pet:
  $ref: "./Pet.yaml"
Pets:
  $ref: "./Pets.yaml"
Error:
  $ref: "./Error.yaml"

schemas は直下がオブジェクト参照にできるので、上記のように index.yaml を作成するとわかりやすいと思います。 中身はすべて子要素(=実態となるオブジェクト)を記載します。

/schemas/Pet.yaml

type: object
required:
  - id
  - name
properties:
  id:
    type: integer
    format: int64
  name:
    type: string
  tag:
    type: string

/schemas/Pets.yaml

type: array
items:
  $ref: "./Pet.yaml"

Pets は配列で子要素に Pet を利用します。 Pet は同じ兄弟フォルダにファイルが存在するのでオブジェクト参照も同一ディレクトリとして相対パスで参照します。

/schemas/Error.yaml

type: object
required:
  - code
  - message
properties:
  code:
    type: integer
    format: int32
  message:
    type: string

/paths/pets.yaml

get:
  summary: List all pets
  operationId: listPets
  tags:
    - pets
  parameters:
    - name: limit
      in: query
      description: How many items to return at one time (max 100)
      required: false
      schema:
        type: integer
        format: int32
  responses:
    '200':
      description: A paged array of pets
      headers:
        x-next:
          description: A link to the next page of responses
          schema:
            type: string
      content:
        application/json:    
          schema:
            $ref: "../schemas/Pets.yaml"
    default:
      description: unexpected error
      content:
        application/json:
          schema:
            $ref: "../schemas/Error.yaml"
post:
  summary: Create a pet
  operationId: createPets
  tags:
    - pets
  responses:
    '201':
      description: Null response
    default:
      description: unexpected error
      content:
        application/json:
          schema:
            $ref: "../schemas/Error.yaml"

schemas を参照したい場合、相対パスだと1つ上のフォルダへ上がる必要があるため、上記のように ../schemas/XXX という表現になります。

/paths/pets.petid.yaml

get:
  summary: Info for a specific pet
  operationId: showPetById
  tags:
    - pets
  parameters:
    - name: petId
      in: path
      required: true
      description: The id of the pet to retrieve
      schema:
        type: string
  responses:
    '200':
      description: Expected response to a valid request
      content:
        application/json:
          schema:
            $ref: "../schemas/Pet.yaml"
    default:
      description: unexpected error
      content:
        application/json:
          schema:
            $ref: "../schemas/Error.yaml"

分割したファイルの結合

swagger-cli を利用すると分割したファイルを結合して1つにすることができます。

swagger-cli は Node.js のツールになるので、 npm でインストールします。 インストールは以下のコマンドで行います。

npm install -g @apidevtools/swagger-cli

以下のコマンドで結合を行います。

swagger-cli bundle -o ./build/openapi.yaml -t yaml ./openapi.yaml

基本のコマンドおよびオプションは以下のような構成になっています。

swagger-cli bundle [options] <file>
-o, --outfile <file>
出力先ファイル名を指定します。
-f, --format <spaces>
インデントのスペース数を指定します。 デフォルトは 2 です。
-t, --type <filetype>
OpenAPIのファイルフォーマットを指定します。 指定できるのは json または yaml です。 デフォルトは json です。

今回は「OpenAPI の ファイル を 分割/結合 する方法」についてまとめました。 参考になったでしょうか? 本記事がお役に立っていると嬉しいです!!

最後に… このブログに興味を持っていただけた方は、 ぜひ 「Facebookページ に いいね!」または 「Twitter の フォロー」 お願いします!!