Swagger定義ファイルを分割する

2016.07.07

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Swagger用ファイルを分割して記述しよう

Swaggerとは

Swaggerとは言語に依存しないREST APIのインターフェース仕様とそれに関連するツール/ライブラリのことです。
RESTful APIの記述標準化を目指している、MS/Google/IBMなどが参加しているグループ、  
Open API Initiativeでは、APIの記述のためにSwaggerが採用されています。

Swaggerは以下のようなツールから構成されています。

  • Swagger UI - swagger specをパースしてAPIドキュメント化するツール
  • Swagger Codegen - swaggerの定義ファイルからプログラムコードを生成するツール
  • Swagger Editor - オンラインで使用できるSwaggerエディタ

普通にswaggerの記述をする

 まずは下記のように、普通にswagger.jsonを記述しましょう。
 Swagger Editorで↓のコードを貼り付けてみると、
 画面右部にAPIドキュメントが表示されます。

{
    "swagger": "2.0",
    "info": {
        "title": "Uber API",
        "description": "Move your app forward with the Uber API",
        "version": "1.0.0"
    },
    "host": "api.uber.com",
    "schemes": [
        "https"
    ],
    "basePath": "/v1",
    "produces": [
        "application/json"
    ],
    "paths": {
        "/me": {
            "get": {
                "summary": "User Profile",
                "description": "The User Profile endpoint returns information.",
                "responses": {
                    "200": {
                        "description": "Profile information for a user",
                        "schema": {
                            "$ref": "#/definitions/Profile"
                        }
                    },
                    "default": {
                        "description": "Unexpected error",
                        "schema": {
                            "$ref": "#/definitions/Error"
                        }
                    }
                }
            }
        }
    },
    "definitions": {
        "Profile": {
            "type": "object",
            "properties": {
                "first_name": {
                    "type": "string",
                    "description": "First name of the Uber user."
                },
                "last_name": {
                    "type": "string",
                    "description": "Last name of the Uber user."
                },
                "email": {
                    "type": "string",
                    "description": "Email address of the Uber user"
                }
            }
        },
        "Error": {
            "type": "object",
            "properties": {
                "code": {
                    "type": "integer",
                    "format": "int32"
                },
                "message": {
                    "type": "string"
                }
            }
        }
    }
}

swaggerの問題点

swaggerである程度のサイズのAPIドキュメントを記述したことがあればわかると思いますが、
swagger.json/yamlファイルは肥大しがちです。
そんなときには、今回紹介するように、swagger.jsonファイルを分割して記述することが可能です。  

環境

今回使用した動作環境は以下のとおりです。

  • OS : MacOS X 10.10.5
  • node : v5.8.0

分割して記述する

では、さきほどのswagger.jsonを分割して記述してみましょう。
まずはルート直下に、index.jsonを下記のように記述します。

{
  "swagger": "2.0",
  "info": {
    "title": "Uber API",
    "description": "Move your app forward with the Uber API",
    "version": "1.0.0"
  },
  "host": "api.uber.com",
  "schemes": [
    "https"
  ],
  "basePath": "/v1",
  "produces": [
    "application/json"
  ],
  "paths": {
    "$ref": "./paths/index.json"
  },
  "definitions": {
    "$ref": "./definitions/index.json"
  }
}

$refを使用して、この後記述するファイルパスを指定しています。
ここではpathsとdefinitionsのindexファイルを指定します。

paths/index.jsonは下記のとおりです。

{
  "/me": {
    "$ref": "./me.json"
  }
}

ここからさらにme.jsonを指定しています。

{
  "get": {
    "summary": "User Profile",
    "description": "The User Profile endpoint returns information.",
    "responses": {
      "200": {
        "description": "Profile information for a user",
        "schema": {
          "$ref": "#/definitions/Profile"
        }
      },
      "default": {
        "description": "Unexpected error",
        "schema": {
          "$ref": "#/definitions/Error"
        }
      }
    }
  }
}

definitions/index.jsonも別ファイルとして指定しているので、作成しましょう。

{
  "Profile": {
    "type": "object",
    "properties": {
      "first_name": {
        "type": "string",
        "description": "First name of the Uber user."
      },
      "last_name": {
        "type": "string",
        "description": "Last name of the Uber user."
      },
      "email": {
        "type": "string",
        "description": "Email address of the Uber user"
      }
    }
  },
  "Error": {
    "type": "object",
    "properties": {
      "code": {
        "type": "integer",
        "format": "int32"
      },
      "message": {
        "type": "string"
      }
    }
  }
}

分割したswaggerの各部分を記述できたら、nodeプログラムを使用してjsonを結合します。
下記のようにresolv.jsファイルを作成します。

//resolv.js
var JsonRefs = require('json-refs');
var root = require('./index.json');

JsonRefs.resolveRefs(root, {filter: ['relative', 'remote']})
    .then(function (res) {
        console.log(JSON.stringify(res.resolved));
    }, function (err) {
        console.log(err.stack);
    });

resolv.jsではjson-refsを使用し、index.jsonを起点にして各JSONを結合します。
jsファイルが記述できたら、下記手順でswagger.jsonを出力してみましょう。

% cd path/your/split-swagger-directory
% npm install json-refs #npmモジュールのインストール
% node resolve.js > swagger.json #結合

 resolv.jsの出力をswagger.jsonにリダイレクトしています。
 swagger.jsonが出力されたらSwagger Editorに貼り付けてみてください。  
 先ほどと同じようにAPIドキュメントが表示されます。

まとめ

今回はswaggerファイルの分割方法について紹介しました。
とにかく肥大しがちな設定ファイルなので、分割して少しでも管理しやすくしましょう。

参考サイトなど