简体   繁体   中英

Springboot - validate @RequestBody

Question: It is possible to validate the JSON payload of a request body, without specifically writing if statements? Maybe via annotation or configuration?

I have a very easy POJO:

public class Foo {

    private int important;
    private String something;

//constructors, getter, seters, toString
}

And a very easy controller class:

@SpringBootApplication
@RestController
public class QuestionController {

    public static void main(String[] args) {
        SpringApplication.run(QuestionController.class, args);
    }

    @GetMapping(value = "/question")
    Mono<String> question(@RequestBody Foo foo) {
        System.out.println("The object foo, with value for important = " + foo.getImportant() + " and something = " + foo.getSomething());
        return Mono.just("question");
    }

}

If I query with a payload such as:

{
    "important": 42,
    "something": "value"
}

Everything is working perfectly fine, very happy.

However, if there is a typo: (note the typo on "important")

{
    "importantWithTypo": 42,
    "something": "value"
}

Or the required "important" is absent (note the JSON is not even complete)

{
    "something": "value"
}

The request and computation are still valid! And the value of "important" is 0!

I do not want Spring to default to 0 and to thinks everything is fine.

I also do not want to change my types from primitives to boxed object.

Without me writing something like:

 @GetMapping(value = "/question")
    Mono<String> question(@RequestBody Foo foo) {
        if (0 == foo.getImportant()) {
            throw new IllegalArgumentException();
        }
        System.out.println("The object foo, with value for important = " + foo.getImportant() + " and something = " + foo.getSomething());
        return Mono.just("question");
    }

What is the most efficient way to resolve this? Some kind of annotation? Or maybe Spring boot configuration?

Thank you

Add @NotNull annotation on a field (you may need to change type to Integer), and add @Valid annotation on the method parameter of the controller.

Mono<String> question(@Valid @RequestBody Foo foo) {
    ...
}
public class Foo {

    @NotNull
    private Integer important;
    private String something;

//constructors, getter, seters, toString
}

You can find more information here: https://lmonkiewicz.medium.com/the-power-of-spring-rest-api-validation-77be83edef

The already provided answer covers the answer.

However I would like to elaborate on one thing that you asked.

How to fail on this "importantWithTypo": 42,

2 aspects to it.

  1. you want to return a 4XX if a required field is not present (this can be achieved by the already given answer) -- @NonNull/@NonEmpty in conjunction with @Validate annotation
  2. You want to error out on presence of an unknown field importantWithTypo . This can be achieved by jackson's fail_on_unknown_properties property. (May be default is fail_on_unknown_properties = enabled, I havent checked so not sure).

Don't do this 2nd thing. That will make your 2 services tightly coupled. By doing this fail_on_unknown_properties = enabled, you are forfeiting the potential opportunity to enhance the consumer/caller service in a nonbreaking fashion. You will have to coordinate both the apps releases.

You also need to add these as dependency to use @Valid , @NotNull etc .

 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>

You can read more on this here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM