Kotlin 数据类和 Bean 验证:长字段上的 @NotNull 不起作用

Tei*_*raz 4 validation kotlin spring-boot

这是数据类:

data class CreateCommentRequest(
        @field:NotNull
        @field:NotEmpty
        val comment: String,

        @field:NotNull
        val postId: Long
)
Run Code Online (Sandbox Code Playgroud)

如果我省略comment字段,验证将正确失败。

但如果我没有通过postId,就像这样:

{
    "comment": "hello"
}
Run Code Online (Sandbox Code Playgroud)

验证通过。

如果postId未通过,如何使验证失败?

PS我使用带有com.fasterxml.jackson.module:jackson-module-kotlin模块的spring boot 2.0.1 ,kotlin版本:1.2.20

Pet*_*art 6

我认为这与https://github.com/FasterXML/jackson-module-kotlin/issues/130有关。

看起来您可以打开DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES,但这不会导致验证错误,但会无法构造对象。您需要适当地处理该异常以生成 400 错误。

如果你真的想要验证,你需要允许构造对象,这样验证器才能运行,这意味着使原始字段可以为空:

data class CreateCommentRequest(
    @field:NotNull
    @field:NotEmpty
    val comment: String,

    @field:NotNull
    val postId: Long?
)
Run Code Online (Sandbox Code Playgroud)

这可能看起来违反直觉,但验证器在对象被构造之前不会运行。它不是 jackson(不关心验证注释)或 kotlin 的一部分。除非您提供了替代实现,否则是基于注释进行空检查的休眠验证器,并且它需要一个完整的对象才能执行此检查。

看起来 jackson kotlin 模块正在创建对象的实例,但它必须为 postId 提供一个值,因此它提供了一个默认值 0(除非您指示它在 null 基元上失败)。

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.kotlin.KotlinModule

data class Test(val x : Long)

fun main(args : Array<String>) {
    val m = ObjectMapper().registerModule(KotlinModule())
    print(m.readValue("{}", Test::class.java)) // prints Test(x=0) 
}
Run Code Online (Sandbox Code Playgroud)

通过使字段可以为空,您就允许构造它,以便 JSR 303 验证可以在对象上运行。

  • 实际上,仅在验证时使非空值可为空是一个非常肮脏的解决方案。有修复了吗? (3认同)