You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中Kotlin类加@Valid后嵌套属性@NotNull校验不生效

核心原因

校验不触发是两个配置问题导致的:

  • Kotlin data class 主构造函数上声明的注解,默认作用于构造器参数,而非类的字段。你在b字段上添加的@Valid、@NotNull没有指定作用目标到字段,Spring Validation扫描字段级别的校验注解时识别不到这两个注解,自然不会触发对应校验。而a字段用了lateinit修饰,注解默认作用到字段上,所以a的校验可以正常生效。
  • 去掉b类型后的?会触发Jackson反序列化报错,是因为没有引入Jackson的Kotlin适配模块,Jackson原生不支持识别Kotlin data class的非空声明、默认值等语法特性,才会抛出异常。

解决方案

第一步:引入必要依赖

首先确保已经引入Spring校验和Jackson Kotlin模块的依赖,Spring Boot 2.3版本之后校验依赖不再默认随web starter引入,需要手动添加。
如果使用Gradle Kotlin DSL:

// 校验核心模块
implementation("org.springframework.boot:spring-boot-starter-validation")
// Jackson Kotlin适配模块,解决反序列化Kotlin类报错问题
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")

如果使用Maven:

<!-- 校验核心模块 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- Jackson Kotlin适配模块 -->
<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-kotlin</artifactId>
</dependency>

引入后Spring Boot会自动完成模块配置,不需要手动注册ObjectMapper的Kotlin模块。

第二步:修正模型类注解

给所有校验注解加上@field:前缀,明确指定注解作用于类字段,同时给必填字段设置默认值null,既避免反序列化报错,又能正常触发校验,不需要使用lateinit:

import java.util.Date
import javax.validation.Valid
import javax.validation.constraints.NotNull

data class MyModel(
    @field:NotNull(message = "a is mandatory")
    var a: String? = null,

    @field:Valid
    @field:NotNull(message = "b is mandatory")
    var b: MyNestedModel? = null
)

data class MyNestedModel(
    @field:NotNull(message = "MyNestedModel.a is mandatory")
    var a: Date? = null,
    @field:NotNull(message = "MyNestedModel.b is mandatory")
    var b: String? = null,
    @field:NotNull(message = "MyNestedModel.c is mandatory")
    var c: String? = null
)

修改后逻辑完全符合预期:

  • 当请求缺失b参数时,Jackson会把b赋值为默认值null,不会抛出反序列化异常,之后@NotNull校验会正常触发,返回自定义的错误信息
  • 当b参数存在时,@Valid注解会生效,级联校验MyNestedModel内部的三个字段规则

可选优化:简化控制器代码

不需要手动注入Validator执行校验,Spring会自动完成校验逻辑,只要在@RequestBody参数前加上@Valid注解即可,控制器可以简化为:

import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RestController
import javax.validation.Valid

@RestController
class MyController {
    @PostMapping("/aa")
    fun sortingRequest(@Valid @RequestBody req: MyModel): ResponseEntity<Any> {
        // 校验不通过时Spring会自动抛出MethodArgumentNotValidException,可以通过全局异常捕获统一返回错误格式
        return ResponseEntity<Any>(null, HttpStatus.CREATED)
    }
}

如果希望保留手动调用validator.validate()的写法也可以,修正注解后手动调用的逻辑也能正常识别b字段的@NotNull和@Valid规则,级联校验嵌套对象。


内容的提问来源于stack exchange,提问作者Code_Worm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 22:30:57