Java 8 date time JSON formatting with Jackson

Carvia Tech | October 24, 2019 | 3 min read | 1 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. Invoking AWS Lambda from a Java Client
  2. What is new in Spring Boot 2
  3. Creating AWS Lambda in Java using Spring Cloud Function
  4. Synechron Java Interview Questions
  5. Prevent Lost Updates in Database Transaction using Spring Hibernate
  6. AWS SDK 2.0 - S3 File upload & download in Java
  7. Invoke AWS Lambda from a Kotlin Client



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