
こんにちは。 エキサイト株式会社の三浦です。
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 を使わずにリクエストモデルを作成するか、いつか対応されることを願いながら気長に待つのが良いかと思います。