简体   繁体   中英

How does Jackson deserializer work by default

I am using Spring-boot 2.1.6 and i have DTO :

@AllArgsConstructor
@Builder
@Data // setters, getters, others
@NoArgsConstructor
public class ExampleDto {
    private String fieldOne;
    private String fieldsTwo;

}

Do i really need that many Lombok annotation here? Which will Jackson use by default when deserializing over HTTP connection (microservices)? I guess only NoArgsConstructor + setters would be fine? Or does it use reflection and only providing no-arg-constructor is fine?

Is there an option to change behaviour of Jackson to use only AllArgsConstructor or builder ? I saw in logs that my app uses Jackson to deserialize stuff.

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.8.8</version>
    <scope>provided</scope>
</dependency>

 <dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jdk8</artifactId>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
</dependency>

Edit:

My question is different from Can't make Jackson and Lombok work together cause it works.

Jackson uses default (no argument) constructor to create object and then sets value using setters. so you only need @NoArgsConstructor and @Setter.

According tothis tutorial jackson searches for getter- and setter-methods. Also to create an object of the type a default constructor is needed. So basically you need a class that satisfies the java bean conventions.

Long story short: You need @Data for getter- and setter-methods and @NoArgsConstructor for the default constructor to satisfy the bean convention. @AllArgsConstructor and @Builder should not be needed for jackson.

Well since you are using Spring Boot, there should be a Jackson configuration class somewhere annotated with @Configuration. Something like this should enable serialization for your Java bean without the need for any annotation

@Configuration
public class JacksonConfiguration {

   @Bean
   public ObjectMapper objectMapper() {
      ObjectMapper mapper = new ObjectMapper();
      objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
      return mapper;
   }

}

The Jackson deserialization by default uses the no-args constructor and the setters of the object. So with Lombok, you'll need a minimum of:

@NoArgsConstructor
@Setter
public class ExampleDto {
    private String fieldOne;
    private String fieldsTwo;
}

(Note if you're ever serializing then you'll need at least a @Getter).

There is an option to override the default deserialization of Jackson to use the Lombok builder. This is covered in top answer to Can't make Jackson and Lombok work together (as others have mentioned). Ie

@Builder
@Data
@JsonDeserialize(builder = ExampleDto.ExampleDtoBuilder.class)
public class ExampleDto {
    private String fieldOne;
    private String fieldsTwo;
}

@JsonPOJOBuilder(withPrefix = "") 
public static class ExampleDtoBuilder {

}

Jackson uses default NoArgsConstructor and Setters.

If you don't provide Setters, jackson will set values using reflection. See - How does jackson set private properties without setters?

Although above answers work to solve the mentioned issue, as an updated answer, according to the lombok official website , from 1.18.14, @Jacksonized was introduced, which automatically configures the generated builder class to be used by Jackson's deserialization. Therefore, your code could be like this:

@Builder
@Jacksonized
public class ExampleDto {
    private String fieldOne;
    private String fieldsTwo;
}

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