Java 8 date time JSON formatting with Jackson

Carvia Tech | October 24, 2019 | 3 min read | 4,448 views


In this tutorial we will learn how to format java 8 date time types (Instant, LocalDate, LocalDateTime, Date) to JSON using Jackson and Spring Boot 2.

Gradle dependencies

First of all we need to create a new Spring Boot 2.2.0 based project. The below gradle file will manage the dependencies for setting up Spring MVC.

build.gradle
plugins {
	id 'org.springframework.boot' version '2.2.0.RELEASE'
	id 'io.spring.dependency-management' version '1.0.8.RELEASE'
	id 'java'
}

group = 'com.shunya'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
}

Creating a POJO

We will create a simple POJO that holds different types of types i.e. java.util.Date, LocalDate, LocalDateTime, Instant.

import com.fasterxml.jackson.annotation.JsonFormat;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;

public class SampleDto {

    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "Asia/Kolkata")
    private Instant instant;

    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
    private Date date;

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

    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
    private LocalDateTime localDateTime;

    //Getters and Setter omitted for brevity
}

We will use this POJO for Jackson based JSON serialization/deserialization.

It is important to note here that we need to specify the timezone while dealing with java.time.Instant otherwise we will encounter the below exception:

nested exception is com.fasterxml.jackson.databind.JsonMappingException: Unsupported field: YearOfEra

Controller Layer

We will create a controller that exposes two endpoints - one with HTTP POST for SampleDto another for HTTP GET for SampleDto.

DateController.java
@RestController
public class DateController {

    @PostMapping("/date")
    public SampleDto create(@RequestBody SampleDto payload) {
        return payload;
    }

    @GetMapping("/date")
    public SampleDto get() {
        final SampleDto dto = new SampleDto();
        final Instant time = Instant.ofEpochMilli(1571884105000L);
        dto.setInstant(time);
        dto.setDate(new Date(time.toEpochMilli()));
        dto.setLocalDate(time.atZone(ZoneId.of("UTC")).toLocalDate());
        dto.setLocalDateTime(time.atZone(ZoneId.of("UTC")).toLocalDateTime());
        return dto;
    }
}

JUNIT 5 test at Controller layer for JSR-310 types

Spring Boot 2.2.0 supports JUNIT5 out of the box without any custom configuration. All you need to do is to include the below dependency in build.gradle

build.gradle
dependencies {
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
}

test {
	useJUnitPlatform()
}

Here we will just test the controller layer using JUNIT 5 based tests in Spring Boot.

DateControllerTest.java
@ExtendWith(SpringExtension.class)
@WebMvcTest(DateController.class)
class DateControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    void postDate() throws Exception {
        //language=JSON
        String jsonPayload = "{\n" +
                "  \"instant\": \"2019-10-24T07:58:25.000+05:30\",\n" +
                "  \"date\": \"2019-10-24T02:28:25.000+0000\",\n" +
                "  \"localDate\": \"2019-10-25\",\n" +
                "  \"localDateTime\": \"2019-10-24T02:28:25\"\n" +
                "}";
        this.mockMvc.perform(MockMvcRequestBuilders
                .post("/date")
                .content(jsonPayload)
                .contentType(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON))
                .andDo(print()).andExpect(status().isOk())
                .andExpect(content().string(CoreMatchers.notNullValue()));
    }
}

WebMvcTest annotation just bootstraps the provided controller instead of loading the entire application context.

Spring DateTimeFormat vs Jackson JsonFormat

@JsonFormat is a Jackson annotation (com.fasterxml.jackson.annotation), while @DateTimeFormat is a Spring annotation.

@JsonFormat controls the formatting during JSON serialization/deserialization of java Date time classes (JSR-310 java.time types - LocalDate/LocalDateTime/Instant/Date, etc)

@DateTimeFormat on the other hand controls formatting of a bean in Spring when it is rendered ina view.

Github Repository

You can grab the github repository for this project from this link: https://github.com/cancerian0684/tutorial-jsonformat-spring-boot


Top articles in this category:
  1. Generate UPI QR Code in Java
  2. SendGrid Attachments with Spring Boot
  3. Invoking AWS Lambda from a Java Client
  4. SendGrid emails in Spring Boot
  5. Java AWS Lambda using Spring Cloud Function
  6. Feign Client Logging and connection timeout
  7. Send Gupshup SMS using Java API


Find more on this topic:
Spring Framework image
Spring Framework

Spring Framework - MVC, Dependency Injection, Spring Hibernate, Spring Data JPA, Spring Boot and Spring Cloud for Microservices Architecture.

Last updated 1 week ago


Recommended books for interview preparation:

This website uses cookies to ensure you get the best experience on our website. more info