こんにちは。 エキサイト株式会社の三浦です。
JavaのSpring Bootでは、OpenAPIのライブラリを使用することでAPIのリクエストモデルを簡単にドキュメント化することができます。
ただ、リクエスト用のモデルで ConstructorProperties
を使っていると、うまいことドキュメント化ができないことがあります。
今回は、 ConstructorProperties
を使ったAPIリクエストモデルでは、 ParameterObject
は使えないという話をしていきます。
Spring BootとOpenAPI
Spring Bootでは、OpenAPIのライブラリを使用することで、以下のようにAPIを簡単にドキュメント化できます。
build.gradle
plugins { // ... id "org.openapi.generator" version "5.4.0" id "org.springdoc.openapi-gradle-plugin" version "1.3.3" // ... }
実コード
package sample; import lombok.RequiredArgsConstructor; import lombok.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RequiredArgsConstructor @RestController @RequestMapping("sample") public class SampleController { @GetMapping public String info(@ModelAttribute SampleRequestModel sampleRequestModel) { return "ok"; } @Value public static class SampleRequestModel { /** * サンプル文字列1 */ String sampleString1; /** * サンプル文字列2 */ String sampleString2; } }
このコードによって、自動的に以下のようなドキュメントが生成されます。
更に、以下のように @ParameterObject
を付けると、より可読性が高まります。
// ... @GetMapping public String info(@ModelAttribute @ParameterObject SampleRequestModel sampleRequestModel) { return "ok"; } // ...
このドキュメントはブラウザ上で見られるのですが、その画面から直接APIへのリクエストもできるため、とても便利なものとなっています。
しかし、実はリクエストモデル上で ConstructorProperties
を使っていると、うまくドキュメント化されないという問題があります。
ConstructorPropertiesを使ったAPIリクエストモデルでは、ParameterObjectは使えない
リクエストモデルを、以下のようにしてみましょう。
// ... @Value public static class SampleRequestModel { /** * サンプル文字列1 */ String sampleString1; /** * サンプル文字列2 */ String sampleString2; @ConstructorProperties({"test_string_1", "test_string_2"}) public SampleRequestModel(String testString1, String testString2) { this.sampleString1 = testString1; this.sampleString2 = testString2; } }
sampleString1
はクエリパラメータ上では test_string_1
として、 sampleString2
はクエリパラメータ上では test_string_2
として受け取るので、ドキュメント上でも test_string_1
と test_string_2
のみが表示されていることが、こちらが意図する挙動となります。
ではまず、@ParameterObject
を付けない状態でドキュメント化するとどうなるかというと、以下のようになります。
なんとこのように、 ConstructorProperties
の値とモデルのプロパティの値の両方が出てしまうのです。
更に @ParameterObject
を付けると、以下のようになってしまいます。
モデルのプロパティの値しか出ず、 ConstructorProperties
の値は出てきません。
まとめ
残念ながら、現状では ConstructorProperties
を使ったAPIリクエストモデルでは、 ParameterObject
は使えないようです。
ConstructorProperties
を使わずにリクエストモデルを作成するか、いつか対応されることを願いながら気長に待つのが良いかと思います。