OpenAPI(Swagger)導入下調べ

![20190326161049.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69002/a00b931e-0e3c-cb79-d0f9-832ed707b3c7.png)

# 概要
前プロジェクト（新規開発）でOpenAPIを導入するために下調べしたときのまとめメモ。

# OpenAPIとは
- API仕様書（HTMLベース）を自動生成できる
- クライアント側(iOSなど)で実装するAPI通信コードを自動生成できる
- サーバー側のAPIインターフェース部分を自動生成できる
- 仮データを返すようなモックサーバーを自動生成できる

上記のようなことを、API定義ファイルを1つ作ることで可能にするAPI仕様書規格。
以前はSwaggerという名前で運営されていたが、技術仕様3.0からOpenAPIという名称に変更された。

参考①：[Qiita記事 OpenAPI (Swagger) 超入門](https://qiita.com/teinen_qiita/items/e440ca7b1b52ec918f1b)
参考②：[Web版Editor(仮データ付き)： Swagger Editor](https://editor.swagger.io/)

# 導入経緯
初期のクライアント（iOSアプリ）開発にあたり、サーバー構成やAPI設計等の作業と並行して動く必要があり、下記のようなことをしたく導入。

- 現状の仕様（←未確定のものも含む）をいったん文書化して、サーバー開発側とコミュニケーションをとりたい
- 上記仕様をクライアント開発にさくっと取り込みたい
- 上記仕様に合わせたモックサーバーをさくっと立てたい

# たどり着いた方法もろもろ
## １，共有方法

Githubに、YAML形式の仕様ファイルを置き共有。

## ２，編集方法

Web版Editorを使って編集するのが手軽だが、編集作業のたびに仕様ファイルをインポート・エクスポートしなければいけないので微妙。

VisualStudio Codeに専用プラグイン[SwaggerViewer](https://marketplace.visualstudio.com/items?itemName=Arjun.swagger-viewer)をインストールして対応。
インストール後、`対象ファイルビュー内で[shift + alt + P]` か `対象ファイル副クリック→PreviewSwagger` でプレビュー画面起動。

## ３，iOSコード取り込み方法

### ３−１コード生成
OpenAPIのコード生成プログラムは2種類。

- **swagger-codegen**: Swagger本家のコード生成プログラム。
- **openapi-generator**: 上記プログラムの一部開発者が立ち上げたOSSなコード生成プログラム。

当初は**swagger-codegen**を使おうとしたものの、コンパイルエラーが出ないよう[テンプレートファイル](https://github.com/swagger-api/swagger-codegen/tree/master/modules/swagger-codegen/src/main/resources/swift4)を使う必要があり、メンテナンス上で難があったため、今回は**openapi-generator**を使って生成。
なお、RxSwiftも使いたかったため、同時にjson形式の設定ファイルも用意。

#### ０，インストール
`brew install openapi-generator`

#### １，設定ファイル(config.json)を用意
```json:最小限の項目
{
  // pod関連設定
  "podSource": "{ :git => \"https://github.com/shoichikuraoka/example_api.git\"}",
  "projectName": "ExampleAPI",
  "podHomepage": "https://github.com/shoichikuraoka/example_api",
  "podSummary": "API example",
  "podVersion": "0.0.1",
  
  // RxSwift的にAPIを使う場合は必要
  "responseAs": "RxSwift"
}
```
※何を設定できるかは`openapi-generator config-help -g swift4`で参照可。

#### ２，生成
`openapi-generator -g swift4 -i 定義書.yaml -o 出力先/`

### ３−２コード取り込み
API通信以外の実装のバージョン管理に影響を与えるのはよくないため、CocoaPods経由で外部ライブラリとして取り込む。

#### １，生成コードのpodspecファイルを編集
```ruby:編集する項目
# プッシュ先のGitURLを指定（コード生成時に設定ファイルでも指定可）
s.source = { :git => "https://github.com/shoichikuraoka/example_api.git"}

# 依存ライブラリのバージョン指定を外す
s.dependency 'RxSwift'
s.dependency 'Alamofire'
```
#### ２，生成コードをgithubリポジトリにプッシュ。

#### ３，アプリ側のPodsファイルを編集
```
pod 'ExampleAPI', :git => 'https://github.com/shoichikuraoka/example_api.git'
```
#### ４，取り込み
`pod install`

## ４，モックサーバー設定方法

### ４−１サーバープログラム立ち上げ
手軽さ重視でapisproutを使用。

#### ０，インストール
[Github: apisprout releases](https://github.com/danielgtaylor/apisprout/releases)から、ビルド済みファイル（apisprout-v1.3.0-mac.tar.xz）をダウンロード。
ダウンロードしたファイルを解凍して実行ファイル（apisprout）を生成。
実行ファイルを`/usr/local/bin/`配下に移動。

#### １，起動
`apisprout 定義書.yaml`

#### ２，確認
`http://localhost:8000/(get系APIパス)`をブラウザに入れてみて動作確認。

#### (ボツ案)
- swagger-codegenでサーバーコードを生成して起動する方法：　手軽じゃない。テストデータが自動で入らない。
- openapi-generatorでサーバーコードを生成して起動する方法：　手軽じゃない。nodejsがOpenAPI3.0に未対応。

### ４−２モックデータの挿入
モデル定義の各プロパティにexampleが入っていれば、それらが入ったモックデータを自動でapisproutが返す。
カスタマイズしたモックデータを返したい場合（例：配列の中身を多めにしたい）は、下記手順でexampleを定義・挿入する。

#### １，モックデータオブジェクトを定義する
components/examples配下に定義する。

```yaml:モックデータオブジェクトの定義
components:
  schemas:
    …(省略)…
  examples:
    kariExampleObject:
      value:
        name: Taro Yamada
        age: 54
```

#### ２，APIレスポンスに挿入
対象APIのレスポンス部分に挿入する。

```yaml:モックデータオブジェクトの挿入
paths:
  /kari:
    get:
      tags:
      - kari
      operationId: getKari
      responses:
        200:
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Kari'
              examples:
                nandemoii_mojiretsu:
                  $ref: '#/components/examples/kariExampleObject'
```

#### ex，直で定義する方法
データオブジェクトが行数も少なく、再利用もしないのであれば下記のように直定義の方がよいかも。

```yaml:モックデータオブジェクトの直定義
paths:
  /kari:
    get:
      tags:
      - kari
      operationId: getKari
      responses:
        200:
          description: successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Kari'
              example:
                name: Taro Yamada
                age: 54
```

#### 参考
- [Swigger.io: Adding-Examples](https://swagger.io/docs/specification/adding-examples/)


# 備考
（特になし）