Kotlin Spring Bean 验证可空性

2022-09-03 02:49:12

在我用 Kotlin 构建的 Spring 应用程序中,我想对如下所示的数据类使用 Bean 验证。

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

    @field: NotBlank
    val lastName: String)

在向客户终端节点发送具有空名字的帖子时,我希望获得约束验证,但由于字段不允许空值,我无法获得验证,而是收到以下错误。

"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 的空安全运算符的确切目的是强制您在代码中显式表达可空性行为,以便大幅减少 NPE,或者至少确保您故意导致它们:)。在您的(或任何类似MVC的访问模式)的情况下,您面临以下情况

  • 字段可能为空,作为 DTO 负载的一部分
  • 如果字段为 null,则框架验证应取消 DTO 的资格。
  • 如果框架验证成功,则隐式假定 DTO 字段不为 null

虽然这在逻辑流方面是有意义的,但它实际上是可能导致NPE的违规,因为模型/契约中没有任何内容保证这些字段不会为空。

不过,在java中,你只是使用getter做了最后的假设(无论如何,你一直在使用getter,它是java,对吧?)。

好吧 - 在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!!
    }

(此示例假定您用于 JSON de/序列化)jackson

虽然仍然使用运算符手动强制非空性(这是您想要避免的),但您现在正在从代码库的其余部分抽象出该方面,从而获得类似java getter的行为。!!


答案 2

我认为更好的解决方案是在属性中使用Kotlin的默认值:

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

@field: NotBlank
val lastName: String="")

名字和姓氏属性将始终具有值(来自 json 或默认值 =“”)。解决方案并不完美,但它像预期的那样工作。


推荐