Search code examples
javaspringspring-bootspring-validatorspring-validation

Validate list inside request with springboot against [null]


My goal is to validate (fail) against a request which looks like this:

{
  "title": "some title",
  "foos": [null]
}

I have this straightforward code:

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";
    }

}
record SomeRequest(

    @NotEmpty(message = "Please enter the title")
    String title,

    @NotNull
    @NotEmpty
    @Valid
    List<@Valid Foo> foos

) {
}
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);
    }

}
<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>

I can confirm this is som how working, since out of my 5 test cases, 4 are good (failing).

1- GOOD:

curl --location 'http://localhost:8080/question' \
--header 'Content-Type: application/json' \
--data '{
  "title": "some title"
}'

2- GOOD:

curl --location 'http://localhost:8080/question' \
--header 'Content-Type: application/json' \
--data '{
  "title": "some title",
  "foos": null
}'

3- GOOD:

curl --location 'http://localhost:8080/question' \
--header 'Content-Type: application/json' \
--data '{
  "title": "some title",
  "foos": []
}'

4- GOOD:

curl --location 'http://localhost:8080/question' \
--header 'Content-Type: application/json' \
--data '{
  "title": "some title",
  "foos": [{}]
}'

However, I would expect this to also fail, but it does not.

curl --location 'http://localhost:8080/question' \
--header 'Content-Type: application/json' \
--data '{
  "title": "some title",
  "foos": [null]
}'

May I ask how can I check against [null]?


Solution

  • You need to add @NotNull to Foo generic param:

    record SomeRequest(
    
                @NotEmpty(message = "Please enter the title")
                String title,
    
                @NotNull
                @NotEmpty
                @Valid
                List<@NotNull @Valid Foo> foos // here @NotNull added
    
        ) {
    }