Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

In Spring Boot 1.2.3.RELEASE with fasterxml what is the correct way of serializing and de-serializing a LocalDate field to ISO date formatted string?

I've tried:

  • spring.jackson.serialization.write-dates-as-timestamps:false in application.properties file,

  • including jackson-datatype-jsr310 in project and then using

  • @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") annotation

  • and @DateTimeFormat(iso=ISO.DATE) annotation,

  • adding Jsr310DateTimeFormatAnnotationFormatterFactory as formatter with:

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addFormatterForFieldAnnotation(new Jsr310DateTimeFormatAnnotationFormatterFactory());
    

    None of the above helped.

    and then following annotations helped:

    @JsonDeserialize(using = LocalDateDeserializer.class)
    @JsonSerialize(using = LocalDateSerializer.class)
    private LocalDate birthday;
    

    Update: if you are using Spring Boot 2.*, the dependency is already included via one of the "starters".

    This fixed it for me. I encountered the deserialization issue when I upgraded to use the 1.3.0.BUILD.SNAPSHOT version of spring boot. – Laran Evans Sep 13, 2015 at 7:19 Yes you need the com.fasterxml.jackson.datatype:jackson-datatype-jsr310 dependency and then you can use @JsonDeserialize @JsonSerialize annotations with the LocalDate field using LocalDateSerializer like in the answer. – aycanadal Oct 3, 2015 at 2:01 Doesn't work for me on SpringBoot 1.3.6.RELEASE ;/ Getting error: com.fasterxml.jackson.datatype.jsr310.ser.JSR310FormattedSerializerBase.findFormatOverrides(Lcom/fasterxml/jackson/databind/SerializerProvider;Lcom/fasterxml/jackson/databind/BeanProperty;Ljava/lang/Class;)Lcom/fasterxml/jackson/annotation/JsonFormat$Value; – thorinkor Jul 13, 2016 at 13:18

    In my Spring Boot 2 applications

  • @JsonFormat annotation is used in REST controllers when (de)serializing JSON data.
  • @DateTimeFormat annotation is used in other controllers ModelAttributes when (de)serializing String data.
  • You can specify both on the same field (useful if you share DTO between JSON and Thymeleaf templates):

    @JsonFormat(pattern = "dd/MM/yyyy") 
    @DateTimeFormat(pattern = "dd/MM/yyyy")
    private LocalDate birthdate;
    

    Gradle dependency:

    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-json'
    

    I hope this is all configuration you need for custom Date/Time formatting in Spring Boot 2.x apps.

    For Spring Boot 1.x apps, specify additional annotations and dependency:

    @JsonFormat(pattern = "dd/MM/yyyy")
    @DateTimeFormat(pattern = "dd/MM/yyyy")
    @JsonDeserialize(using = LocalDateDeserializer.class)
    @JsonSerialize(using = LocalDateSerializer.class)
    private LocalDate birthDate;
    // or
    @JsonFormat(pattern = "dd/MM/yyyy HH:mm")
    @DateTimeFormat(pattern = "dd/MM/yyyy HH:mm")
    @JsonDeserialize(using = LocalDateTimeDeserializer.class)
    @JsonSerialize(using = LocalDateTimeSerializer.class)
    private LocalDateTime birthDateTime;
    
    implementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: '2.9.8'
    

    Be aware that your API will throw "JSON parse error" if somebody sends a date in a wrong format. Mapping example:

    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate releaseDate;
    

    Exception example:

    HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type java.time.LocalDate from String "2002": Failed to deserialize java.time.LocalDate: (java.time.format.DateTimeParseException) Text '2002' could not be parsed at index 4; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type java.time.LocalDate from String "2002": Failed to deserialize java.time.LocalDate: (java.time.format.DateTimeParseException) Text '2002' could not be parsed at index 4

    If you want to use a custom Java Date formatter, add the @JsonFormat annotation.

    @JsonFormat(pattern = "dd/MM/yyyy")
    @JsonDeserialize(using = LocalDateDeserializer.class)
    @JsonSerialize(using = LocalDateSerializer.class)
    private LocalDate birthdate;*
                    You should offer a way to set it globally. Adding @JsonFormat for every POJO is tedious. The answer from @chen should be the best.
    – V.Tran
                    May 4 at 8:39
    

    Actually, it works if you just specify the dependency in the pom.xml.

    With this, all my LocalDate fields automatically use the ISO format, no need to annotate them:

    <!-- This is enough for LocalDate to be deserialized using ISO format -->
    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jsr310</artifactId>
    </dependency>
    

    Tested on Spring Boot 1.5.7.

    Instead of specifying the serializer/deserializer for all your LocalDate attributes, you might be interested in registering it globally. You need to override the configuration of the default ObjectMapper used by Spring for serialization/deserialization. Here is an example:

    @Configuration
    public class ObjectMapperConfiguration {
        @Bean
        @Primary
        public ObjectMapper objectMapper() {
            ObjectMapper mapper = new ObjectMapper();
            // Registro global do serializer/deserializer para datas sem horário
            SimpleModule simpleModule = new SimpleModule();
            simpleModule.addSerializer(LocalDate.class, new LocalDateSerializer());
            simpleModule.addDeserializer(LocalDate.class, new LocalDateDeserializer());
            mapper.registerModule(simpleModule);
            return mapper;
    

    This way, Jackson will always use the specified serializer/deserializer for the data type defined, without the need to annotate your classes attributes.

    Info: you must add the jackson-databind dependency to your pom.xml to have the custom serializer/deserializer code feature:

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.13.3</version>
    </dependency>
    
     @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
        return builder -> {
            DateTimeFormatter localDateFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
            builder.serializerByType(LocalDate.class, new LocalDateSerializer(localDateFormatter));
            builder.deserializerByType(LocalDate.class, new LocalDateDeserializer(localDateFormatter));
            DateTimeFormatter localDateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
            builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(localDateTimeFormatter));
            builder.deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer(localDateTimeFormatter));
            

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.

  •