OpenAPI仕様のYAMLファイルからDartコードを自動生成する際に、タグに日本語は使わない方が良いという話

こんにちは、エキサイト株式会社の平石です。

エキサイトホールディングス Advent Calendar 2023の22日目を担当いたします。

OpenAPI仕様に基づいてAPIの仕様を定義したYAMLファイルから、アプリ用のDartコードを自動生成する際に、タグの指定で注意すべき点がありました。

実際に、APIとアプリ側の繋ぎ込みを行なう際に問題となったため、ブログとして残しておこうと思います。

OpenAPIとは

本ブログでは、Dartコードを自動生成する部分の説明は省きます。

以下で紹介されていますので、こちらもご覧ください。

tech.excite.co.jp

タグに日本語は使わない方が良い?

結論から述べますと、タグに日本を指定してしまったことで、問題が発生しました。
以下で、日本語を指定することで発生する現象を詳細にご紹介します。

今回はYAMLファイルからコードを自動生成することを考えます。

以下のように、APIを定義したYAMLファイルを用意します。

openapi: 3.0.1
info:
  title: OpenAPI definition
  version: v0
servers:
- url: http://localhost:8190
  description: Generated server url
paths:
  /article:
    get:
      tags:
      - 記事
      summary: 記事取得
      operationId: getArticle
      responses:
        "200":
          description: 正常に処理が終了した場合
          content:
            application/text:
              schema:
                type: string
components: {}

余談ですが、このYAMLファイルは以下のようなSpringBoot製のControllerを持つAPIから生成しました。

@RestController
@RequestMapping("article")
@Tag(name = "記事")
public class ArticleGetController {
    @GetMapping
    @Operation(summary = "記事取得")
    @ApiResponses(value = {
            @ApiResponse(
                    responseCode = "200",
                    description = "正常に処理が終了した場合",
                    content = @Content(mediaType = "application/text", schema = @Schema(implementation = String.class))
            )
    })
    public String getArticle() {
        return "Article";
    }
}

YAMLファイルの11, 12行目でtagsに「記事」というタグを指定しています。

この、tagsに指定した文字列によってエンドポイントが分類されます。
また、自動生成されるDartのコードの「どのクラスに、どのエンドポイントに対応するコードが生成されるか」もこのタグを元に決定されます。

しかし、このタグの設定に上記の「記事」のような英数字以外の文字を入れてしまうと、コード生成がうまくいきません。

この挙動を見てみましょう。

同じ「記事」というタグを設定した記事投稿のエンドポイントと、「ユーザー」というタグを設定したユーザー取得のエンドポイントの定義を追加してみます。

openapi: 3.0.1
info:
  title: OpenAPI definition
  version: v0
servers:
- url: http://localhost:8190
  description: Generated server url
paths:
  /article/post:
    post:
      tags:
      - 記事
      summary: 記事投稿
      operationId: postArticle
      responses:
        "201":
          description: 正常に処理が終了した場合
          content:
            application/text:
              schema:
                type: string
  /user:
    get:
      tags:
      - ユーザー
      summary: ユーザー取得
      operationId: getUser
      responses:
        "200":
          description: 正常に処理が終了した場合
          content:
            application/text:
              schema:
                type: string
  /article:
    get:
      tags:
      - 記事
      summary: 記事取得
      operationId: getArticle
      responses:
        "200":
          description: 正常に処理が終了した場合
          content:
            application/text:
              schema:
                type: string
components: {}

これらのエンドポイントを作成した上で、swagger-ui(http://localhost:8190/swagger-ui/index.html)を確認すると以下のようになっているはずです。

指定したタグによって、「記事」と「ユーザー」で分類がなされていることがわかります。
Swaggerまでは英数字以外のタグも認識してくれるようです。

それでは、アプリ用のDartコードを自動生成してみます。

OpenAPIを使って、Spring Boot製のAPIからアプリ用のDartコードを自動生成する - エキサイト TechBlog. の内容に従って、自動生成を行ないます。

すると、generated/dart/lib/src/api配下にdefault_api.dartファイルが作成されます。

この中身を見ると、すべてのエンドポイントに対応するコードがdefault_api.dart内に生成されてしまっています。

これは、タグを全く指定せずにコードを自動生成した時と同じ結果です。

一方、記事articleユーザーuserのように英数字のみを使うようにすると、以下のように2つのファイルに分かれて生成されます。

このように、dartファイルの自動生成の段階では。英数字のタグしか認識されず、日本語のタグは無視されてしまうようです。
タグがファイル名やクラス名の一部になるという仕様になっているようなので、当然と言えば当然の挙動かもしれません。

もう一つ、以下のような現象も発生します。

「記事API」「ユーザーAPI」というタグを設定した2つのエンドポイントを作成することを考えます。

〜 略 〜

paths:
  /user:
    get:
      tags:
        - ユーザーAPI

〜 略 〜

  /article:
    get:
      tags:
        - 記事API

〜 略 〜

「記事」と「ユーザー」という2つの異なる要素を扱うエンドポイントに対応する自動生成のコードが、別々のファイルに生成されることを期待した設定です。
しかし、この場合、api_api.dartというファイルに2つのエンドポイントに対応するコードが生成されるという、予期しない動作をします。

日本語の部分(「記事」「ユーザー」)が無視され、英数字である「API」という部分だけが認識された結果、どちらも「API」というタグを指定した時と同じ結果になったと考えられます。

最も、全てのコードがdefault_api.dart内等の同じファイルに生成されたとしても、実際のコードには動作上問題ありません。
しかし、自動生成されたコードが分類されていた方が、可読性や利便性の観点で優れていると考えられます。
そのため、タグの指定には英数字以外は使わないようにするのが無難でしょう。

終わりに

今回は、OpenAPI仕様のYAMLファイルからアプリ用のDartコードを自動生成する際には、タグの指定に注意する必要があるということを紹介しました。

では、また次回。