Logo

dev-resources.site

for different kinds of informations.

Formatting json Date/LocalDateTime/LocalDate in Spring Boot

Published at
9/21/2022
Categories
springboot
jackson
localdatetim
Author
kevinblandy
Categories
3 categories in total
springboot
open
jackson
open
localdatetim
open
Author
11 person written this
kevinblandy
open
Formatting json Date/LocalDateTime/LocalDate in Spring Boot

Spring Boot uses jackson by default to serialize, deserialize json data.

By default, Jackson serializes Date objects as timestamps. For LocalDateTime, LocalDate objects, jackson doesn't do anything special, it just treats them as basic Java objects.

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.databind.ObjectMapper;

public class MainTest {

    public static void main(String... args) throws Exception {
        ObjectMapper objectMapper = new ObjectMapper();

        Map<String, Object> map = new HashMap<>();
        map.put("date", new Date());
        map.put("localDateTime", LocalDateTime.now());
        map.put("localDate", LocalDate.now());

        String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(map);

        System.out.println(json);
    }
}
Enter fullscreen mode Exit fullscreen mode

Output.

{
  "date" : 1663680273923,
  "localDateTime" : {
    "dayOfMonth" : 20,
    "dayOfWeek" : "TUESDAY",
    "dayOfYear" : 263,
    "month" : "SEPTEMBER",
    "monthValue" : 9,
    "year" : 2022,
    "hour" : 21,
    "minute" : 24,
    "nano" : 992000000,
    "second" : 33,
    "chronology" : {
      "id" : "ISO",
      "calendarType" : "iso8601"
    }
  },
  "localDate" : {
    "year" : 2022,
    "month" : "SEPTEMBER",
    "era" : "CE",
    "dayOfMonth" : 20,
    "dayOfWeek" : "TUESDAY",
    "dayOfYear" : 263,
    "leapYear" : false,
    "monthValue" : 9,
    "chronology" : {
      "id" : "ISO",
      "calendarType" : "iso8601"
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

The above code runs normally in Java8. If you are in a higher version of java, such as java17, running the above code may throw an exception.

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type `java.time.>LocalDateTime` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through >reference chain: java.util.HashMap["localDateTime"])
   at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
   at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1300)
   at com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer.serialize(UnsupportedTypeSerializer.java:35)
   at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeFields(MapSerializer.java:808)
   at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeWithoutTypeInfo(MapSerializer.java:764)
   at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:720)
   at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:35)
   at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
   at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
   at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1518)
   at com.fasterxml.jackson.databind.ObjectWriter._writeValueAndClose(ObjectWriter.java:1219)
   at com.fasterxml.jackson.databind.ObjectWriter.writeValueAsString(ObjectWriter.java:1086)
   at io.springboot.test.MainTest.main(MainTest.java:22)

Date

The formatting of the Date object can be easily customized through the configuration properties provided by spring boot.

spring:
  jackson:
    # Date format string or a fully-qualified date format class name. For instance, 'yyyy-MM-dd HH:mm:ss'
    date-format: "yyyy-MM-dd HH:mm:ss.SSS"
    # Locale used for formatting
    time-zone: "GMT+8"
Enter fullscreen mode Exit fullscreen mode

LocalDateTime & LocalDate

Spring Boot does not provide configuration properties for formatting LocalDateTime and LocalDate, but it does provide a Jackson2ObjectMapperBuilderCustomizer interface to easily customize the formatting of LocalDateTime and LocalDate.

import java.time.format.DateTimeFormatter;

import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;

@Configuration
public class JacksonConfiguration {

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {

        return builder -> {

            // formatter
            DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            DateTimeFormatter dateTimeFormatter =  DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

            // deserializers
            builder.deserializers(new LocalDateDeserializer(dateFormatter));
            builder.deserializers(new LocalDateTimeDeserializer(dateTimeFormatter));

            // serializers
            builder.serializers(new LocalDateSerializer(dateFormatter));
            builder.serializers(new LocalDateTimeSerializer(dateTimeFormatter));
        };
    }
}

Enter fullscreen mode Exit fullscreen mode

Testing

A simple test to verify that the above code and configuration takes effect.

Controller

A simple Controller that reads and parses the client's request body into a payload object, which defines the LocalDate, LocalDateTime fields. And it responds to the client with the payload object to verify that the custom formatting is working.

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import lombok.Data;

@Data
class Payload {
    private LocalDate date;
    private LocalDateTime  dateTime;
}

@RestController
@RequestMapping("/test")
public class TestController {

    @PostMapping
    public Object test (@RequestBody Payload payload) {
        Map<String, Object> ret = new HashMap<>();
        ret.put("payload", payload); // request body
        ret.put("now", new Date());
        return ret;
    }
}

Enter fullscreen mode Exit fullscreen mode

Client

Use Postman to launch http requests.

POST /test HTTP/1.1
Content-Type: application/json
User-Agent: PostmanRuntime/7.29.2
Accept: */*
Postman-Token: 1b1cbcad-475e-49a9-ad5d-5a8163bd7b05
Host: localhost
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 70

{
"date": "2022-09-20",
"dateTime": "2022-09-20 21:02:00"
}

HTTP/1.1 200 OK
Content-Encoding: gzip
Connection: keep-alive
Server: PHP/7.3.1
X-Request-Id: 6038513c-fa65-49bf-8e6c-44f5db749832
Transfer-Encoding: chunked
Content-Type: application/json
Date: Tue, 20 Sep 2022 14:18:09 GMT

{"payload":{"date":"2022-09-20","dateTime":"2022-09-20 21:02:00"},"now":"2022-09-20 22:18:09.318"}
Enter fullscreen mode Exit fullscreen mode

With the request and response logs, you can see that everything is OK.

For more information about the available configurations of jackson in spring boot, you can refer to the official documentation

Reference https://www.springcloud.io/post/2022-09/springboot-date-format/

jackson Article's
30 articles in total
Favicon
Why Do We Still Need Jackson or Gson in Java?
Favicon
A simple GeoJSON serializer for Jackson
Favicon
[Java Spring Boot] Como Criar Serializador Personalizado para seus Responses ou Json de saída
Favicon
[Java Spring Boot] How to implement a Custom Serializer for your Responses or Json
Favicon
[Java SpringBoot] Como Criar Deserializador Personalizado para seus Requests
Favicon
[Java SpringBoot] How to implement a Custom Deserializer for your Requests
Favicon
Java Jackson JSON: How to Handle Custom Keys?
Favicon
Create a custom Jackson JsonSerializer und JsonDeserializer for mapping values
Favicon
Anotación @JsonUnwrapped
Favicon
A tale of fixing a tiny OpenAPI bug
Favicon
Kotlin Springboot -- Part 21 任意の key value の json を POST する API E2E を書く
Favicon
Formatting json Date/LocalDateTime/LocalDate in Spring Boot
Favicon
Jackson's @JsonView with SpringBoot Tutorial
Favicon
Jackson JSON parsing top-level map into records
Favicon
Using Jackson Subtypes to Write Better Code
Favicon
Java – Convert Excel File to/from JSON (String/File) – using Apache Poi + Jackson
Favicon
How to resolve Json Infinite Recursion problem when working with Jackson
Favicon
Java – Convert Excel File to/from JSON (String/File) – using Apache Poi + Jackson
Favicon
Practical Java 16 - Using Jackson to serialize Records
Favicon
Kotlin – Convert Object to/from JSON with Jackson 2.x
Favicon
💾 Java Records 💿 with Jackson 2.12
Favicon
Jackson, JSON and the Proper Handling of Unknown Fields in APIs
Favicon
Polymorphic deserialization with Jackson and no annotations
Favicon
Playing around with Kotlin Sealed Classes
Favicon
Moonwlker: JSON without annotation
Favicon
Jackson Readonly properties and swagger UI
Favicon
Registering Jackson sub-types at runtime in Kotlin
Favicon
Parsing JSON in Spring Boot, part 1
Favicon
Customize how Jackson does LocalDate Parsing
Favicon
Painless JSON with Kotlin and jackson

Featured ones: