【Swagger】使ってみた

## 概要

API開発を初めて、仕様書を作成するにあたって、**API Blue print**を使おうと思ったが、
Swaggerが主流のようなので初めて使ってメモを残す。

## [Swaggerとは](https://swagger.io/docs/specification/about/)

>Swaggerは**OpenAPI仕様(旧名Swagger仕様)**に基づいて構築された一連のオープンソースツールであり、REST APIの設計、構築、文書化、および使用に役立つ。

OpenAPI仕様 => **REST API を定義するための業界標準**

### 主なSwaggerツール

|ツール名|説明|
|:--:|:--:|
|[Swagger Editor](http://editor.swagger.io/#)|ブラウザでオンラインでAPI仕様を記述できる<br>※オフラインでもできます|
|[Swagger UI](https://swagger.io/swagger-ui/)|OpenAPI仕様をAPIドキュメントとしてレンダリングする為のツール|

### Swaggerのいいところ

- **Swagger UI**を使用してAPIドキュメントを生成すると、ユーザーは**<font color="red">ブラウザでAPI呼び出しを直接試すことができる</font>**

## 導入手順(ローカルでやる場合)
### 1.SwaggerEditorをcloneする

```
$ git clone https://github.com/swagger-api/swagger-editor.git
```

### 2.SwagerEditor起動

```
$ open swagger-editor/index.html
```

これでブラウザが起動します！

<img width="961" alt="スクリーンショット 2018-05-10 16.00.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/133737/ebd7601b-19e1-3c55-cc10-d1d8cd71ae45.png">

あとはヘッダーから`File > Clear Editor`でマッサラにして仕様書を作成するだけ。

## 仕様

- 商品情報を管理している**products**テーブルへのAPI操作

※今回はたださわってみただけの記事なので、テーブル構造は鬼シンプルに、またHTTPリクエストも下記1ずつにします。

### HTTPリクエスト

|リクエスト名|path|機能|
|:--:|:--:|:--:|
|GET|`api/`|全件取得|
|POST|`api/`|1件登録|
|PUT|`api/{id}`|対象の1件のレコードの内容の更新|
|DELET|`api/{id}`|対象の1件のレコードを削除|

### テーブル定義
#### products

|カラム名|データ型|Key|
|:--:|:--:|:--:|
|id|int|PK|
|name|varchar(255)||


## 完成したymlファイル

コメントアウトで説明が書かれているのでご覧ください。

```yml
# swaggerのバージョン定義
swagger: "2.0"
# APIについての情報を書く
info:
  # API名
  title: "商品情報API"
  # APIのバージョン
  version: "1.0.0"
  # APIの説明
  description: "productsテーブルのレコードを登録・更新・取得・削除するAPI"
#APIのホスト名 
host: "localhost:8000"
#API共通のpathを記載する
basePath: "/api/v1"
# 対象のテーブル名?を書く
tags:
- name: "products"
  description: "productsテーブル"
schemes:
# スキーマ
- "http"
# APIのエントリポイントを記述
paths:
  #URIを記載する
  /products:
    # GETリクエスト
    get:
      # 前述したタグ名
      tags: 
      - "products"
      #概要
      summary: "商品情報取得"
      #詳細説明
      description: "productsテーブルに登録されている商品情報を全件取得する"
      # content-typeの指定
      produces: 
      - "application/json"
      # レスポンスに関する記述
      responses:
        #statusCode200の時
        200:
          description: "成功"
          # レスポンスのbodyについて記述する
          schema:
            # jsonの場合,だけ？objectを指定する
            type: "object"
            # bodyの中身(ダミー値でいい)
            properties:
              id: 
                #データ型
                type: "integer"
                #ダミー値
                example: "1"
              name:
                type: "string"
                example: "hogehoge"
    # POSTリクエスト
    post:
      tags: 
      - "products"
      summary: "商品情報登録"
      description: "商品情報をproductsテーブルに1件登録する"
      produces: 
      - "application/json"
      # リクエストのbodyについて記述する
      parameters:
      # パラメータの名前
      - name: "body"
        # パラメータの場所
        in: "body"
        required: true
        schema:
          type: "object"
          properties:
            name:
              type: "string"
              example: "piyopiyo"
      responses:
        200:
          description: "成功"
          schema:
            type: "object"
            properties:
              id: 
                type: "integer"
                example: "2"
              name:
                type: "string"
                example: "piyopiyo"
        400:
          description: "失敗"
          schema:
            type: "object"
            properties:
              message:
                type: "string"
                example: "Bad Request"
  # リクエストによって値が変わるパラメータは`{}`で囲む
  /model1/{id}:
    # PUTリクエスト
    put:
      tags:
      - "products"
      summary: "商品情報更新"
      description: "URIで指定したidのproductsテーブルの商品情報を更新する"
      produces:
      - "application/json"
      parameters:
      - name: "id"
        in: "path"
        description: "更新対象のid"
        required: true
        # データ型
        type: "integer"
      - name: "body"
        in: "body"
        description: "更新内容"
        required: true
        schema:
          type: "object"
          properties:
            name:
              type: "string"
              example: "fugafuga"
      responses:
        200:
          description: "成功"
          schema:
            type: "object"
            properties:
              id: 
                type: "integer"
                example: "1"
              name:
                type: "string"
                example: "fugafuga"
        400:
          description: "失敗"
          schema:
            type: "object"
            properties:
              message:
                type: "string"
                example: "Bad Request"
    # DELETEリクエスト
    delete:
      tags:
      - "products"
      summary: "商品情報削除"
      description: "URIで指定したidのproductsテーブルの商品情報を削除する"
      produces: 
      - "apllication/json"
      parameters:
      - name: "id"
        in: "path"
        description: "削除対象の商品id"
        required: true
        type: "integer"
      responses:
        204:
          description: "削除の戻り値"
```

## プレビュー

こんな感じになりました(うまくスクショ取れずすみません🙏)

<img width="719" alt="スクリーンショット 2018-05-10 22.04.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/133737/86e4073e-8083-e9f5-d14d-2220989364c9.png">
<img width="721" alt="スクリーンショット 2018-05-10 22.05.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/133737/d5006250-36a7-feab-d0a8-53bdaa5efc1d.png">
<img width="721" alt="スクリーンショット 2018-05-10 22.05.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/133737/e04db1f5-5130-e10b-da66-10dfe73194fc.png">
<img width="720" alt="スクリーンショット 2018-05-10 22.05.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/133737/2c8ba022-de8e-aa84-076a-de2aa0c52de7.png">
<img width="720" alt="スクリーンショット 2018-05-10 22.05.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/133737/e994366a-f312-8f5a-8bfd-687522b0adcf.png">

## おまけ

レスポンスbodyのjsonの階層を深くしたい場合は下記の様に記述すればいけます！👍

```yml
responses:
  #statusCode200の時
  200:
    description: "成功"
    # レスポンスのbodyについて記述する
    schema:
      # jsonの場合,だけ？objectを指定する
      type: "object"
      # bodyの中身(ダミー値でいい)
      properties:
        status:
          type: "integer"
          example: "200"
        products:
          properties:
            id: 
              #データ型
              type: "integer"
              #ダミー値
              example: "1"
            name:
              type: "string"
              example: "hogehoge"
```

### スクショ

<img width="678" alt="スクリーンショット 2018-05-10 22.24.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/133737/20d4ad17-0d30-ffc3-74f1-28a0408dd934.png">

# おわり

次はhtml生成するところやりたいと思います


## 参照

[Swaggerでいますぐドキュメントを書きたい/読みたい人のためのセットアップガイド](https://qiita.com/shinkuFencer/items/d24896a2d3ae5c30ff29)
[開発効率を上げる！Swaggerの記法まとめ](http://tech.starttoday-tech.com/entry/swagger_yaml#swagger)