Kotlin Spring Bean 検証の null 可能性 質問する

Kotlin Spring Bean 検証の null 可能性 質問する

Kotlin で構築された Spring アプリケーションでは、次のようなデータ クラスで Bean 検証を使用したいと思います。

data class CustomerDto(
    @field: NotBlank
    val firstName: String,

    @field: NotBlank
    val lastName: String)

空の firstName を含む投稿を顧客エンドポイントに送信するときに、制約検証を取得したいのですが、フィールドが null 値を許可していないため、検証は取得されず、次のエラーが発生します。

"status": 400,
"error": "Bad Request",
"message": "JSON parse error: Instantiation of [simple type, class pkg.CustomerDto] value failed for JSON property firstName due to missing (therefore NULL) value for creator parameter firstName which is a non-nullable type; nested exception is com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException: Instantiation of [simple type, class pkg.CustomerDto] value failed for JSON property firstName due to missing (therefore NULL) value for creator parameter firstName which is a non-nullable type\n at [Source: (PushbackInputStream); line: 19, column: 1] (through reference chain: pkg.CustomerDto[\"firstName\"])",
"path": "/shop/5/customer"

dto フィールドをオプションではないとマークして、制約違反が発生する他のオプションはありますか? オプションとしてマークすると、エンティティにマッピングするときに、コード内の null 不可のフィールドに !! を使用する必要があります。

ありがとう。

ベストアンサー1

あなたは間違ったやり方で取り組んでいると思います。

Kotlin の null 安全演算子の正確な目的は、NPE を大幅に最小限に抑えるために、または少なくとも自分で意図的に NPE を発生させないようにするために、コード内で null 可能性の動作を明示的に表現するように強制することです :)。あなたの場合 (または MVC のようなアクセス パターンの場合)、次のシナリオに直面します。

  • DTO ペイロードの一部としてフィールドが null になる可能性がある
  • フィールドが null の場合、フレームワーク検証では DTO を不適格とする必要があります。
  • フレームワークの検証が成功した場合、DTOフィールドは暗黙的に null ではないと想定される

論理的な流れとしては理にかなっていますが、モデル/契約ではこれらのフィールドがnullにならないことを保証していないため、実際にはNPEを引き起こす可能性のある違反です。

それでも、Java では、getter を使用して最終的な仮定を行うことになります (Java なので、いずれにしても getter を使用するはずです)。

そうですね、それが必要なのであれば、Kotlin でも違いはありません。

data class CustomerDto(@field:NotNull 
                       @JsonProperty("firstName") private val _firstName: String? = null,
                       @field:NotNull
                       @JsonProperty("lastName") private val _lastName: String? = null) {
        val firstName get() = _firstName!!
        val lastName get() = _lastName!!
    }

(この例では、jacksonJSON のデシリアライゼーション/シリアル化に使用していることを前提としています)

演算子を使用して手動で非NULL可能性を強制しながら!!(これは避けたいことでしたが)、その側面をコードベースの残りの部分から抽象化し、Javaのgetterのような動作を実現しています。

おすすめ記事