Kotlin 原语的 Spring 验证

Posted

技术标签:

【中文标题】Kotlin 原语的 Spring 验证【英文标题】:Spring validation for Kotlin primitives 【发布时间】:2021-01-18 02:41:21 【问题描述】:

我使用 Kotlin 1.4.10 创建了 simple Spring Boot project。

我在项目中有简单的 DTO:

data class TestRequest(
        @field:NotNull val id: Int,
        val optionalId: Int?,
        val name: String,
        val optionalName: String?,
        @field:NotNull val value: Double,
        val optionalValue: Double?,
        val nested: NestedRequest,
        val optionalNested: NestedRequest?
)

data class NestedRequest(
        @field:NotNull val nestedId: Long,
        val nestedOptionalId: Long?,
        val nestedName: String,
        val optionalNestedName: String?

)

我想知道,编写 Kotlin DTO 并验证它们的最佳实践是什么?

一方面,Kotlin 允许将字段标记为非空,这似乎便于验证。 从另一个角度来看,对于 Kotlin 数字类型(Int、Long、Double 等),它似乎具有默认值,就像 Java 原语一样,因此检查可空性不适用于与字符串不同的字段。

如果我使用@JsonProperty(required = true),Jackson 会检查可空性而不是验证器,所以这种方法也是不正确的。

因此,我有一个问题 - 有没有一种验证 Kotlin DTO 的正确方法?

【问题讨论】:

【参考方案1】:

正如您所注意到的,很难验证 kotlin 原始类型的可空性,因为它们具有默认值。

我会说结合使用 Jackson(用于原始类型的可空性)和 Javax 验证(诸如最小值/最大值之类的东西)很好。

但是,如果您不想使用 Jackson 验证,则可以通过将变量的类型设置为可为空但将其注释为 @NotNull 来验证原始类型。

例如:

import javax.validation.Valid
import javax.validation.constraints.NotNull

data class MyClass(
        @get:Valid
        @get:NotNull
        val someInt: Int?,
        val someText: String
)

现在,因为类型可以为空(在本例中为 Int?),Jackson 不会为 someInt 插入默认值,因此 someInt 将具有 null 的值。之后,当对象被验证时,会抛出错误,因为someInt 的值为空。

例如,如果我们有以下@PostMapping

    @PostMapping("/test")
    fun testFunction(@RequestBody @Valid data: MyClass) 
        print(data)
    

发送带有正文的 POST 请求:


    "someText": "wow"

会返回类似这样的错误:

  "timestamp": "2020-10-02T15:22:53.361+00:00",
  "status": 400,
  "error": "Bad Request",
  "trace": "org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public void main.api.TestPublicController.myObject(main.api.MyClass): [Field error in object 'myClass' on field 'someInt': rejected value [null]; ...

【讨论】:

以上是关于Kotlin 原语的 Spring 验证的主要内容,如果未能解决你的问题,请参考以下文章

android RecyclerView pinch zoom,ScaleGestureDetector&GridLayoutManager,with BigImageViewer,kotli

Kotlin Spring bean 验证可空性

Kotlin Spring Boot bean 验证不起作用

Kotlin和Spring Boot请求身体验证

Kotlin Spring Boot 中的控制器验证

Kotlin Spring Boot Webflux 使用 @Valid 注解验证 @RequestBody