📖

Springdoc-openapiでOpenAPIドキュメント作成

2024/10/02に公開

はじめに

Rehab for JAPAN の宍戸です。
デイサービス向けの記録アプリ Rehab Cloudデイリー のバックエンド開発を担当しています。
バックエンドではSpringBoot(Kotlin)を使用しており、Springdoc-openapiでAPIドキュメントの作成を行っています。
本記事ではその導入手順や使い方を解説します。

ターゲット

  • Spring Boot を使用している Java または Kotlin 開発者
  • APIドキュメントの自動生成ツールを探している方
  • Spring BootプロジェクトにSpringdoc-openapiを導入したい方

Springdoc-openapiとは

Springdoc-openapiは、Spring Bootアプリケーションの OpenAPIドキュメントを自動生成するためのライブラリです。
コードからドキュメントを生成するため、常に最新の状態を保つことができます。

https://springdoc.org/

環境設定

  • Spring Boot: 3.x
  • Kotlin: 1.8.x
  • Java: 17
  • Gradle: 7.x

セットアップ

  1. 依存関係の追加

build.gradle.ktsファイルに以下の依存関係を追加します。

dependencies {
    implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    }
  1. Springdoc-openapi の設定

application.propertiesまたはapplication.ymlファイルで設定を変更できます。

springdoc:
  api-docs:
    path: /docs/api-docs # OpenAPIドキュメント(JSON)のパス
  swagger-ui:
    path: /swagger-ui.html # swagger-uiのパス

参考:Springdoc-openapi Properties

API全体のメタ情報を定義する

アプリケーションクラスに@OpenAPIDefinitionアノテーションを追加することで、API全体の情報(タイトル、バージョン、説明など)を定義できます。

@OpenAPIDefinition(
    info = Info(
        title = "Springdoc-openapi sample",
        version = "1.0",
        description = "Springdoc-openapiのサンプルです",
    )
)
@SpringBootApplication
class SpringdocOpenapiSampleApplication
  • Swagger UIでの表示

基本的なAPIエンドポイントの作成とドキュメント化

Springdoc-openapiでは、様々なアノテーションを使用してAPIのドキュメントを自動生成します。
主要なアノテーションとその使用方法について説明します。

まずは、基本的なGETリクエストとPOSTリクエストのエンドポイントを例として示します。
これらのエンドポイントは、ユーザー情報の取得と新規ユーザー作成を行うものです。

GETリクエストの例

@RestController
@RequestMapping("/api/users")
class UserController {

    @Operation(
        summary = "ユーザー情報の取得",
        description = "指定されたIDのユーザー情報を返します。ユーザーが存在しない場合は404エラーを返します。"
    )
    @ApiResponses(value = [
        ApiResponse(responseCode = "200", description = "成功"),
        ApiResponse(responseCode = "404", description = "ユーザーが見つかりません")
        ApiResponse(
             responseCode = "500",
             description = "サーバーエラー",
             content = [Content(schema = Schema(implementation = ErrorResponse::class))]
         )
    ])
    @GetMapping("/{id}")
    fun getUser(
        @Parameter(description = "ユーザーID", required = true, example = "12345")
        @PathVariable id: Int
    ): ResponseEntity<UserResponse> {
        // 実装省略
        return ResponseEntity.ok(UserResponse(id, "ユーザー$id", 30))
    }
}

data class UserResponse(
    @Schema(description = "ユーザーID", example = "12345")
    val id: Int,
    @Schema(description = "ユーザー名", example = "John Doe")
    val name: String,
    @Schema(description = "ユーザーの年齢", minimum = "0", maximum = "150")
    val age: Int
)

POSTリクエストの例

@RestController
@RequestMapping("/api/users")
class UserController {

    @Operation(
        summary = "新規ユーザーの作成",
        description = "ユーザー情報を受け取り、新規ユーザーを作成します。"
    )
    @ApiResponses(value = [
        ApiResponse(responseCode = "201", description = "ユーザーが作成されました"),
        ApiResponse(responseCode = "400", description = "無効なリクエストデータ")
    ])
    @PostMapping
    fun createUser(
        @RequestBody @Parameter(description = "作成するユーザーの情報") 
        user: CreateUserRequest
    ): ResponseEntity<UserResponse> {
        // 実装省略
        return ResponseEntity.status(HttpStatus.CREATED).body(UserResponse(1, user.name, user.age))
    }
}

data class CreateUserRequest(
    @Schema(description = "ユーザー名", example = "John Doe", required = true)
    val name: String,
    @Schema(description = "ユーザーの年齢", example = "30", minimum = "0", maximum = "150")
    val age: Int,
    @Schema(description = "メールアドレス", example = "john@example.com")
    val email: String
)

主要アノテーションの説明

  1. @Operation

    • 目的:APIエンドポイントの詳細情報を定義します。
    • 主なパラメータ:
      • summary: 操作の簡潔な概要
      • description: 操作の詳細な説明
    • 例:
      @Operation(
          summary = "ユーザー情報の取得",
          description = "指定されたIDのユーザー情報を返します。ユーザーが存在しない場合は404エラーを返します。",
      )
      
    • Swagger UIでの表示
  2. @Parameter

    • 目的:メソッドパラメータの詳細を定義します。
    • 主なパラメータ:
      • description: パラメータの説明
      • required: 必須かどうか
      • example: パラメータの例
    • 例:
      @GetMapping("/{id}")
      fun getUser(
          @Parameter(description = "ユーザーID", required = true, example = "12345")
          @PathVariable id: Int
      ): ResponseEntity<UserResponse>
      
    • Swagger UIでの表示
  3. @ApiResponses@ApiResponse

    • 目的:APIエンドポイントの可能なレスポンスを定義します。
    • 主なパラメータ:
      • responseCode: HTTPレスポンスコード
      • description: レスポンスの説明
      • content: レスポンスのコンテンツ(ボディ)の定義
    • 例:
      @ApiResponses(value = [
          ApiResponse(responseCode = "200", description = "成功"),
          ApiResponse(responseCode = "404", description = "ユーザーが見つかりません"),
          ApiResponse(
              responseCode = "500",
              description = "サーバーエラー",
              content = [Content(schema = Schema(implementation = ErrorResponse::class))]
          )
      ])
      
    • Swagger UIでの表示
  4. @Schema

    • 目的:モデルクラスやフィールドのスキーマ情報を定義します。
    • 主なパラメータ:
      • description: フィールドの説明
      • example: フィールドの例
      • required: 必須かどうか
      • minimum, maximum: 数値の最小値と最大値
    • 例:
      data class UserResponse(
          @Schema(description = "ユーザーID", example = "12345", required = true)
          val id: Int,
          
          @Schema(description = "ユーザー名", example = "John Doe", required = true)
          val name: String,
          
          @Schema(description = "ユーザーの年齢", minimum = "0", maximum = "150")
          val age: Int
      )
      
    • Swagger UIでの表示

ドキュメントの確認

./gradlew bootRunでアプリケーションを起動し、以下のURLにアクセスしてOpenAPIドキュメントを確認できます。

まとめ

Springdoc-openapiを使用することで、Spring Bootアプリケーションの OpenAPIドキュメントを簡単に自動生成できます。
また実装の変更に応じてドキュメントも自動更新されるため、コードとドキュメントが常に一致する状態を保てるのが利点です。

サンプルコードについては、こちらのリポジトリをご確認ください。
https://github.com/shota-shishido/springdoc-openapi-sample

Rehab Tech Blog

Discussion