LoginSignup
4
4

More than 3 years have passed since last update.

Nest.jsでSwagger (Open API) とバリデーション用のデコレータを記述する

Last updated at Posted at 2019-12-07

@nestjs/swaggerが4.x(3.xと並行開発されていたnextブランチ)になり、Open API (Swagger 3.0) がサポートされるようになった。class-validatorを使ったバリデーションと組み合わせたときのデコレータの記述について、一般的なREST APIでの実装例を以下のサンプルプロジェクトにまとめた。

以下では、サンプルプロジェクトを作成する際に気づいたことをまとめている。

クエリパラメータの記述方法

OpenAPI定義に利用する@ApiQuery(@nestjs/swagger)はMethod Decoratorのため、Controllerメソッドに設定する必要がある。一方でバリデーション定義(class-validator)ではProperty DecoratorをDTOクラスに設定する。それぞれ単純に設定すると似たような制約条件の記述場所が離れてしまうので、OpenAPIの制約条件をSchemaObjectに分離して、DTOクラスと同じファイルに記述するとよい。

my-controller.ts

@Controller('path/to/controller')
class MyController {
  @ApiQuery({ 
    name: 'myParam',
    description: 'A query parameter',
    schema: MyParamSchema
  })
  @Get()
  get(@Query() query: MyQuery): MyBody { ... }
}

my-query.ts

export class MyQuery {
  @MaxLength(32)
  myParam?: string;
}

const MyParamSchema: SchemaObject = {
  maxLength: 32,
  type: 'string',
}
export { MyParamSchema }
(参考)@ApiPropertyをクエリパラメータに使うときの問題点

単純にDTOクラスにOpenAPIの制約条件を記述する方法として、@ApiPropertyを使うことが考えられるが、このデコレータはリクエストボディに利用されることを想定しているようで、クエリパラメータに設定するとparameters直下に制約条件のプロパティが出力されて、OpenAPIの仕様違反となる。

class MyQuery {
  @MaxLength(32)
  @ApiProperty({ maxLength: 32 })
  param?: string;
}

上記のDTOクラスから出力されるOpenAPIは下記のようになる。

parameters:
  - name: myQuery
    in: query
    maxLength: 100

(OpenAPI仕様上は下記のようにクエリパラメータの制約条件はschemaプロパティに指定する必要がある。)

parameters:
  - name: Offset
    in: query
    schema:
      maxLength: 100
クエリパラメータで数値を受け取る

クエリパラメータには型を定義する方法がないため、Nest.jsではstring型として扱われる。数値用のバリデーションデコレータを利用できるようにclass-transformerを使ってnumber型で受け取るとよい。

class QueryParam {
    @Type(() => Number)
    @Min(0)
    @ApiPropertyOptional({
      description: 'Offset',
      minimum: 0,
      example: 5,
    })
    offset?: number;
}
その他課題など

現時点では以下のような使いにくいポイントがある。(今後改善されていく?)

  • @nestjs/commonで定義したリクエストは@nestjs/swaggerに反映されるが、レスポンスは反映されないため、別にOpenAPI用の定義を記述する必要がある。
    • 例えば、@HttpCode (common) でレスポンスのステータスコードを変更したとしても、Open APIドキュメントに反映するには別途@ApiResponse (swagger) を記述する必要がある。
  • 別のライブラリのため当然だが、class-validatorと@nestjs/swaggerのアノテーションはそれぞれ設定する必要がある。
    • ドキュメントに記載する定義域と実際のバリデーションルールを分離したい場合は問題ないが、同じでよい場合は同じルールを2か所に記載することになる。
  • Open APIドキュメントを出力するにはひと手間必要になる。(参考:#158
4
4
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
4
4