swaggerでWeb APIの定義を管理してみるmmj blog

エンジニア 伊藤
エンジニア 伊藤
2019年07月12日


React等で開発されたフロントエンドからバックエンドのWeb APIを呼び出す場合、APIの定義を管理するのはわりと手間がかかります。パラメータの型や必須項目の有無をドキュメントで管理すると実際のソースコードと差異がでていたり、バックエンドを修正したらフロントエンドの修正が漏れていた…というのはよくあることです。
swaggerを使うとこういった場合に効率よく開発できます。

例えば、ユーザーを検索する場合のAPI定義を考えてみます。
名前・メールアドレス・年齢で検索できるようにURL・パラメータ・レスポンスを定義します。

swaggerではAPI定義はYAML形式(またはJSON形式)で定義します。
Swagger Editor で構文をチェックしながら編集できます。
(一部抜粋)

  '/user/search':
    get:
      parameters:
      - name: name
        in: query
        type: string
      - name: mail
        in: query
        type: string
      - name: age
        in: query
        type: integer
      responses:
        200:
          description: OK
          schema:
            type: array
            items:
              $ref: '#/definitions/User'

レスポンスのJSONは以下のように定義します。
ID・名前・メールアドレス・電話番号・年齢・有効フラグを返します。

  User:
    type: object
    required:
    - id
    - name
    - mail
    - enable
    properties:
      id:
        type: integer
      name:
        type: string
      mail:
        type: string
      tel:
        type: string
      age:
        type: integer
      enable:
        type: boolean

こうして定義した内容を元に、swagger-codegen を使用するとコードを生成することができます。
フロントエンドのコード(typescript)を生成するにはAPI定義をファイルに保存し以下のコマンドを実行します。

java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate -i sample.yaml -l typescript-fetch -o src-client/

ここではAPI定義を sample.yaml に保存しています。
パラメータの -i は定義ファイルのパス、 -l は出力する言語、 -o は出力先のディレクトリを指定します。

生成された src-client/api.ts を開くと、モデルやAPI呼び出しのコードがあります。

export interface User {
    /**
     * 
     * @type {number}
     * @memberof User
     */
    id: number;
    /**
     * 
     * @type {string}
     * @memberof User
     */
    name: string;

...

    public userSearchGet(name?: string, mail?: string, age?: number, options?: any) {
        return DefaultApiFp(this.configuration).userSearchGet(name, mail, age, options)(this.fetch, this.basePath);
    }

同様に、バックエンドのコード(java, play-framework)を生成するには以下のコマンドを実行します。

java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate -i sample.yaml -l java-play-framework -o src-server/

生成された src-server/app/controllers/DefaultApiControllerImp.java を開くとサーバ側APIの空の実装があります。

    @Override
    public List userSearchGet(String name, String mail, Integer age) throws Exception {
        //Do your magic!!!
        return new ArrayList();
    }

いかがでしょうか。
フロントエンドとバックエンドのコードを両方生成することによりパラメータの相違をなくすことができます。
これ以外にも、swaggerにはAPIを呼び出すテスト画面を表示したりドキュメントを生成する機能もあります。
API部分の開発・メンテナンスに工数がかかっている場合は導入を検討してよいかと思います。

参考:swagger-codegenを実行するには

Ubuntuにswaggerをダウンロードしてビルドするには以下のコマンドを実行します。
※JDKとgitとmavenが必要です。

git clone https://github.com/swagger-api/swagger-codegen.git
cd swagger-codegen
mvn clean package

以下のコマンドを実行して使用可能な言語の一覧が表示されれば完了です。

java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar

参考:API定義のサンプル

swaggerでコードが生成できるか確認した定義の内容です。

swagger: "2.0"
info:
  title: "swagger sample"
  version: "1.0"

paths:

  '/user/show':
    get:
      parameters:
      - name: userId
        in: query
        type: integer
        required: true
      responses:
        200:
          description: OK
          schema:
            $ref: '#/definitions/User'

  '/user/search':
    get:
      parameters:
      - name: name
        in: query
        type: string
      - name: mail
        in: query
        type: string
      - name: age
        in: query
        type: integer
      responses:
        200:
          description: OK
          schema:
            type: array
            items:
              $ref: '#/definitions/User'

  '/user/update':
    post:
      parameters:
      - name: body
        in: body
        required: true
        schema:
          $ref: '#/definitions/User'
      responses:
        200:
          description: OK
          schema:
            $ref: '#/definitions/User'

definitions:
  User:
    type: object
    required:
    - id
    - name
    - mail
    - enable
    properties:
      id:
        type: integer
      name:
        type: string
      mail:
        type: string
      tel:
        type: string
      age:
        type: integer
      enable:
        type: boolean

2019年07月12日

エンジニア 伊藤 |

«
このページのトップへ