Search code examples
javaspring-bootjacksonjson-deserializationjava-time

Is there any option to register Serializer/Deserializer only once for java.time.* packages using Jackson in Spring Boot?


Hello Team,

I am working on a Spring Boot Project (Version 2.3.4 Release) in which I am using java.time.LocalDate, java.time.LocalDateTime and java.time.LocalTime datatypes for some of the properties in several beans.

However, these fields are not getting deserialized automatically unless I am explicitly providing following annotations to them along with my custom deserializer.

@JsonFormat(pattern="dd-MMM-yyyy")
@JsonDeserialize(using= LocalDateWithStringsDeserializer.class)
private LocalDate date_of_joining;

It is really a time consuming job to add these annotations to all the beans as there are more than 400-500 beans in this project.

If these annotations were not provided, I get below error.

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.LocalDate` (no Creators, like default construct, exist): no String-argument constructor/factory method to deserialize from String value ('27-May-1999')

I have also tried defining a explicit Bean for overriding Spring Boot objectmapper with my custom deserializers but that even didn't helped me. The code snippet of the same is mentioned below.

@Bean
@Primary
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
    ObjectMapper objectMapper = builder.build();
    objectMapper.findAndRegisterModules();
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    objectMapper.setDateFormat(dateformat);
    SimpleModule module = new SimpleModule();
    module.addDeserializer(LocalDateTime.class, new MillisOrLocalDateTimeDeserializer());
    module.addDeserializer(LocalDate.class, new LocalDateWithStringsDeserializer());
    module.addDeserializer(LocalTime.class, new LocalTimeWithStringDeserializer());
    objectMapper.registerModule(module);
    return objectMapper;
}

I have even added following dependencies to pom.xml file in my project.

    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jsr310</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.module</groupId>
        <artifactId>jackson-module-parameter-names</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jdk8</artifactId>
    </dependency>
    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
    </dependency>

Please suggest a solution.


Solution

  • So I figured out the solution. There were some other object mappers previously configured which were using Joda Time in a project which was added to the build path of my project as a required library.

    Modifying the existing object mappers and registering Java Time module and custom deserializers for Date & Time with them in that project like I have mentioned in this question resolved this issue.