jsonからswagger specを生成するコマンドをdictknifeに取り込んだ

以前に、jsonからswagger specを生成するツールを作っていたのだけれど。とくにリポジトリを分けておく必要性もなかったのでdictknifeに取り込んだ。

ついでに、swagger独自っぽい雰囲気のしたコマンドはswaggerknifeとして別のコマンドにすることにした。

以前は2つだったコマンドが3つになった。

  • dictknife
  • jsonknife
  • swaggerknife

jsonknife flatten は実質definitions以下だけを対象にしているなどからswaggerknifeに移動した。

$ swaggerknife -h
Usage: swaggerknife [OPTIONS] COMMAND [ARGS]...

Options:
  --log [WARNING|INFO|NOTSET|CRITICAL|WARN|ERROR|DEBUG]
                                  logging level
  -h, --help                      Show this message and exit.

Commands:
  flatten       flatten jsonschema sub definitions
  json2swagger  json2swagger

json2swagger

実際のところyaml2swaggerにもtoml2swaggerにもなるのだけれど。名前はjson2swaggerのまま。後で良い名前が思いついたらそれに変える。

例えば、以下のようなjsonから以下のようなswagger specが生成できる(例は http://qiita.com/futoase/items/fd697a708fcbcee104de から)。

config.json

{
  "server": {
    "host": "localhost",
    "port": "3306",
    "slave": [
      {"weight": 1, "ip": "10.0.0.1"},
      {"weight": 5, "ip": "10.0.0.2"},
      {"weight": 3, "ip": "10.0.0.3"},
      {"weight": 2, "ip": "10.0.0.4"}
    ]
  },
  "db": {
    "user": "root",
    "pass": "pass"
  }
}

以下のようなコマンドを経由してswagger specを生成

$ swaggerknife json2swagger --name config config.json > config.spec.yaml

config.spec.yaml

definitions:
  slaveItem:
    type: object
    properties:
      weight:
        type: integer
        example: 1
      ip:
        type: string
        example: 10.0.0.1
    required:
    - weight
    - ip
  slave:
    type: array
    items:
      $ref: '#/definitions/slaveItem'
  server:
    type: object
    properties:
      host:
        type: string
        example: localhost
      port:
        type: string
        example: '3306'
      slave:
        $ref: '#/definitions/slave'
    required:
    - host
    - port
    - slave
  db:
    type: object
    properties:
      user:
        type: string
        example: root
      pass:
        type: string
        example: pass
    required:
    - user
    - pass
  config:
    type: object
    properties:
      server:
        $ref: '#/definitions/server'
      db:
        $ref: '#/definitions/db'
    required:
    - server
    - db

requiredなどはきつめに設定する様になっている。

validationしたい

validationしたいのだけれど。swaggerのvalidationを入れるのもめんどくさかったのでjsonschemaでvalidationできるようにした。 jsonschemaとしてはinvalidではあるけれどjsonschemaというpythonのライブラリでは検証できる程度には整えた出力を返すようにした。

# jsonschema コマンドが実行できるようになる
$ pip install jsonschema
# --dstでjsonやjsの拡張子のファイルを指定するとJSONのフォーマットで返す
$ swaggerknife json2swagger --emit=jsonschema config.json --dst schema.json
# とりあえずjsonschemaで検証
$ jsonschema -i config.json schema.json

yaml形式でschemaを渡すことなどはできなそうなので、yamlを受け取れるvalidation用のコマンドがあっても良いかもしれない。 ちなみにschema.json以下のような感じ。

{
  "type": "object",
  "properties": {
    "server": {
      "$ref": "#/definitions/server"
    },
    "db": {
      "$ref": "#/definitions/db"
    }
  },
  "required": [
    "server",
    "db"
  ],
  "definitions": {
    "slaveItem": {
      "type": "object",
      "properties": {
        "weight": {
          "type": "integer",
          "example": 1
        },
        "ip": {
          "type": "string",
          "example": "10.0.0.1"
        }
      },
      "required": [
        "weight",
        "ip"
      ]
    },
    "slave": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/slaveItem"
      }
    },
    "server": {
      "type": "object",
      "properties": {
        "host": {
          "type": "string",
          "example": "localhost"
        },
        "port": {
          "type": "string",
          "example": "3306"
        },
        "slave": {
          "$ref": "#/definitions/slave"
        }
      },
      "required": [
        "host",
        "port",
        "slave"
      ]
    },
    "db": {
      "type": "object",
      "properties": {
        "user": {
          "type": "string",
          "example": "root"
        },
        "pass": {
          "type": "string",
          "example": "pass"
        }
      },
      "required": [
        "user",
        "pass"
      ]
    }
  }
}