5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

OpenAPI3:プロパティのoptionalとnullableの書き方

Last updated at Posted at 2021-03-08

ちょうど、こないだ書いたOpenAPI genarator の typescript-fetch について、他所で言及されていたのですが、その内容が軽く引っかかったので書いておきます。

レスポンスデータのプロパティがオプショナル(?)になる?

レスポンスデータのプロパティ全部に ? がついている(オプショナルな)ため、とても扱いづらい。API的には絶対あるはずの項目なのに、いちいちチェックを入れなければならない

? を外すの、一番最悪の場合は生成されたコードをさらに加工するという頭の悪い手段はありますが、それは本当の最終手段としたい。

すくなくとも私の手元ではそんなことにはならないので、ひょっとして type:object の時、requiredを指定してないんじゃないのかな? と思うのですが、どうなんでしょうか。

オプショナルなプロパティ

Specで下記のようなオブジェクトが定義されていた場合、オブジェクトのプロパティはすべてオプショナルになります。

components:
  schemas:
    ApiResponse:
      type: object
      description: APIレスポンス
      properties:
        code:
          type: integer
          description: レスポンスコード
          minimum: 0
        type:
          type: string
          description: レスポンスタイプ
        message:
          type: string
          description: メッセージ

↓ Codegen して出力されてくるtypescriptの定義。

api.ts
/**
 * 
 * @export
 * @interface ApiResponse
 */
export interface ApiResponse {
    /**
     * 
     * @type {number}
     * @memberof ApiResponse
     */
    code?: number;
    /**
     * 
     * @type {string}
     * @memberof ApiResponse
     */
    type?: string;
    /**
     * 
     * @type {string}
     * @memberof ApiResponse
     */
    message?: string;
}

code type message すべてのプロパティがオプショナルになっており、ひょっとして元記事ではこの事を言っているのかなと思ったのですが、だとすると、これはSpec的に正しい解釈です。

オプショナルではないプロパティは、required に記述されている必要があります。
下記のSpecから Codegen されたTSでは、プロパティはオプショナルにはなりません。

components:
  schemas:
    ApiResponse:
      type: object
      description: APIレスポンス
      properties:
        code:
          type: integer
          description: レスポンスコード
          minimum: 0
        type:
          type: string
          description: レスポンスタイプ
        message:
          type: string
          description: メッセージ
      required:
          - code
          - type
          - message
api.ts
/**
 * APIレスポンス
 * @export
 * @interface ApiResponse
 */
export interface ApiResponse {
    /**
     * レスポンスコード
     * @type {number}
     * @memberof ApiResponse
     */
    code: number;
    /**
     * レスポンスタイプ
     * @type {string}
     * @memberof ApiResponse
     */
    type: string;
    /**
     * メッセージ
     * @type {string}
     * @memberof ApiResponse
     */
    message: string;
}

nullable なプロパティ

一方で、nullable:true なプロパティがTypescript側に反映されないようだ、という現象は確認していますが、どうやらnullableについては根深い問題のようで、プロパティ値に null を入れるぐらいなら、プロパティごと null にしておいた方が無難であるようです。

typescript-fetch について

元記事では、他に2点の不満が挙げられており、typescript-fetch の出来が悪いというご意見のようです。

あまりにも OpenAPI generator のクォリティに難がありすぎるため、時間があれば pure js で書かれた、別のコード生成を試したかったところです。もしくはもういっそ自作した方が確実なのでは?とすら思っています。

別にtypescript-fetch に対して思い入れも義理もないですが、酷い言われようだなと思ったので、ついでに残り2点も擁護しておきます。

クラスやメソッドが探しにくい?

API種別ごとにクラスがあって、細かいエンドポイントごとに、メソッドが生えるため、目的のクラスとメソッドを探し出すのが面倒くさい

そんなに探しにくいですかね?
むしろそのための Swagger UI による自動ドキュメント生成だと思っているのですが。

こないだ書いた通り、typescript-fetch で出力されてくるフォーマットは タグ名がAPIクラス名となり、オペレーションID名がメソッド名となります。

↓のようなSpecであれば、Typescript側のコードでは AccountApi.postAccountAuth() がメソッドとなります。

  /account/auth:
    post:
      tags:
        - account
      summary: ログイン
      operationId: postAccountAuth
      responses:
        '200':
          description: successful
        '400':
          description: bad request
        '404':
          description: not found

クラス、メソッドを探すのが辛いということは、オペレーションIDを定義するための規約に問題があるんじゃないのかなあと思うのですが、どうなんでしょうね。
個人的には、下記のOpenAPI設計規約がとても勉強・参考になりました。

もし、 Swagger UI の出力の中に オペレーションID名 が表示されないのが不便である、という意味なら、表示するための設定があるそうです。

axiosより使いにくい?

挙動が typescript-axios と全く別もの

そりゃまあ別物なんでしょう、という話なんですが。

「挙動」というのが、Codegenの挙動なのか、吐き出されたTSの挙動なのか分かりませんが、ここではTSの話だと仮定して、そんなに差がありますかね?

accountApi.postAccountAuth().then((res) => {
  // Success

}).catch((error) => {
  // Error

})

返ってくるのが Promise なんで、レスポンスを受ける分には、特に差異を感じたことがないんですけど、もっと別の段階の話かもしれませんね。

私も使用歴は浅いので、使い込んでいくと色々と不満は出てくるのだろうと思います。

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?