Home > OS >  Spring boot @RequestBody default POJO mapping behavior?
Spring boot @RequestBody default POJO mapping behavior?

Time:09-06

I have a java class with uppercase field names and some of them with under scroll, like this:

public class DATADto {
  private String UPPERCASE;
  private String UNDER_SCROLL;

  public String getUPPERCASE() { return UPPERCASE; }
  public void setUPPERCASE(String s) { UPPERCASE = s; }
  ...//setters and getters
}

and I used this in a rest endpoint that accepts json in a spring rest controller:

@RestController
@RequestMapping({"/api/path"})
public class MyRestController {
   @PostMapping(path = {"/Data"}, consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE)

    public ResponseEntity<?> useDATADto(@RequestBody DATADto aDATADto ) {
     //do something
    }
}

what JSON fields do I need to send by default and why?

CodePudding user response:

It will depend on the Jackson property naming strategy. The default is LOWER_CAMEL_CASE , so your request body should look like this:

{
    "uppercase": "test",
    "under_scroll": "test"
}

For all possible configurations of the naming strategy for Jackson please refer to the document «Class PropertyNamingStrategy»

If you're using Spring, you may use this property to configure the naming strategy:

spring.jackson.property-naming-strategy

Another possible way will be the bean configuration:

@Bean
public Jackson2ObjectMapperBuilder jacksonBuilder() {
     Jackson2ObjectMapperBuilder jacksonMapper = new Jackson2ObjectMapperBuilder();
     jacksonMapper.propertyNamingStrategy(PropertyNamingStrategy.LOWER_CASE);
     return jacksonMapper;
}

Additional note:

Your current naming approach doesn't follow the Java Code Conventions. If you need to process JSON with some specific naming format better to use the @JsonProperty annotation on the fields of your POJO.

Please see the example below:

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

@Data
public class DATADto {
    @JsonProperty("UPPERCASE")
    private String uppercase;
    @JsonProperty("UNDER_SCROLL")
    private String underScroll;
}

CodePudding user response:

You should send post request to /api/path/data with this request body:

{
    "uppercase": "YOUR_VALUE",
    "under_scroll": "YOUR_VALUE"
}

CodePudding user response:

The story goes like this..

Spring Boot by default uses Jackson ObjectMapper to serialize and deserialize Java objects.

In this context, by serialization we mean the conversion of java objects into json, deserialization is the reverse process.

Regarding the @RequestBody annotation, the following is written in the documentation:

Annotation indicating a method parameter should be bound to the body of the web request. The body of the request is passed through an HttpMessageConverter to resolve the method argument depending on the content type of the request. Optionally, automatic validation can be applied by annotating the argument with @Valid.

In short, @RequestBody annotation tells Spring to deserialize an incoming request body into an object passed as a parameter to the handler method. Spring achieves this using MessageConverter

Since Spring Boot uses Jackson by default for serializing and deserializing request and response objects in your REST APIs, and Jackson uses MappingJackson2HttpMessageConverter, so that will be message converter implementation that spring will use. You can read more about that here.

The important thing is that Jackson uses Java Bean naming conventions to figure out the json properties in a Java class. Acutally it uses default PropertyNamingStrategy . Here is what is written in documentation:

In absence of a registered custom strategy, default Java property naming strategy is used, which leaves field names as is, and removes set/get/is prefix from methods (as well as lower-cases initial sequence of capitalized characters).

So, since you didn't set any naming strategy, it will use default one.

Beacause of that, if you send payload like this :

{
    "uppercase": "YOUR_VALUE",
    "under_scroll": "YOUR_VALUE"
}

That won't work, you will get exception, since there jackson won't find under_scroll property in your class, it will look for under_SCROLL , therefore this payload:

{
    "uppercase": "YOUR_VALUE",
    "under_SCROLL": "YOUR_VALUE"
}

will work.

To change default PropertyNamingStrategy check this article.

  • Related