SpringBoot中如何校验包含[null]的请求List参数
问题:如何校验包含null元素的List参数?
我需要让以下请求在校验时失败:
{ "title": "some title", "foos": [null] }
现有代码实现
Controller类
import jakarta.validation.Valid; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController class FieldValidationController { @PostMapping("/question") String question(@Valid @RequestBody SomeRequest someRequest) { return "test"; } }
请求实体类SomeRequest
record SomeRequest( @NotEmpty(message = "Please enter the title") String title, @NotNull @NotEmpty @Valid List<@Valid Foo> foos ) { }
Foo实体类
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import java.util.Map; @NotNull record Foo(@NotNull @NotEmpty String name, @NotNull @NotEmpty Map<String, Object> themap) { }
启动类
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication class FieldValidationApplication { public static void main(String[] args) { SpringApplication.run(FieldValidationApplication.class, args); } }
Maven POM文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.4.1</version> <relativePath/> <!-- lookup parent from repository --> </parent> <artifactId>question</artifactId> <properties> <maven.compiler.source>23</maven.compiler.source> <maven.compiler.target>23</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
测试情况
以下4种请求均能正常触发校验失败:
- 缺少foos字段
curl --location 'http://localhost:8080/question' \ --header 'Content-Type: application/json' \ --data '{ "title": "some title" }'
- foos为null
curl --location 'http://localhost:8080/question' \ --header 'Content-Type: application/json' \ --data '{ "title": "some title", "foos": null }'
- foos为空数组
curl --location 'http://localhost:8080/question' \ --header 'Content-Type: application/json' \ --data '{ "title": "some title", "foos": [] }'
- foos包含空对象
curl --location 'http://localhost:8080/question' \ --header 'Content-Type: application/json' \ --data '{ "title": "some title", "foos": [{}] }'
但以下请求未触发校验失败,不符合预期:
curl --location 'http://localhost:8080/question' \ --header 'Content-Type: application/json' \ --data '{ "title": "some title", "foos": [null] }'
解决方案
问题根源在于:@Valid注解仅会对List中的非null元素触发校验逻辑。当List包含null元素时,不会实例化Foo类,Foo类上的@NotNull注解自然不会生效。要解决这个问题,需要直接在List的元素级别添加@NotNull约束,确保每个元素都不能为null。
修改SomeRequest中foos字段的定义,在泛型参数上添加@NotNull:
record SomeRequest( @NotEmpty(message = "Please enter the title") String title, @NotNull @NotEmpty @Valid List<@NotNull @Valid Foo> foos ) { }
修改后,当foos数组中包含null元素时,@NotNull会直接触发校验失败,无需依赖Foo类的校验逻辑。另外,Foo类上的@NotNull注解可以移除,因为List元素已经通过@NotNull保证非null,Foo的字段校验会在元素非null时由@Valid正常触发。
内容的提问来源于stack exchange,提问作者PatPanda
相关产品推荐
相关产品推荐

