- Jackson java time instant
- Fields inherited from class com.fasterxml.jackson.databind.ser.std.StdSerializer
- Constructor Summary
- Method Summary
- Methods inherited from class com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializerBase
- Methods inherited from class com.fasterxml.jackson.databind.ser.std.StdSerializer
- Methods inherited from class com.fasterxml.jackson.databind.JsonSerializer
- Methods inherited from class java.lang.Object
- Field Detail
- INSTANCE
- _useTimestamp
- _formatter
- _shape
- Constructor Detail
- InstantSerializer
- InstantSerializer
- Method Detail
- withFormat
- withFeatures
- createContextual
- getSchema
- acceptJsonFormatVisitor
- useTimestamp
- _useTimestampExplicitOnly
- How to convert Jackson deserialized ISO8601 formatted date-time into Java8 Instant
- Using LocalDateTime and Custom De-serializer
- Using @JsonFormat()
- Related Topics
- Jackson java time instant
- Fields inherited from class com.fasterxml.jackson.databind.ser.std.StdSerializer
- Constructor Summary
- Method Summary
- Methods inherited from class com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializerBase
- Methods inherited from class com.fasterxml.jackson.databind.ser.std.StdSerializer
- Methods inherited from class com.fasterxml.jackson.databind.JsonSerializer
- Methods inherited from class java.lang.Object
- Field Detail
- INSTANCE
- _useTimestamp
- _formatter
- _shape
- Constructor Detail
- InstantSerializer
- InstantSerializer
- Method Detail
- withFormat
- withFeatures
- createContextual
- getSchema
- acceptJsonFormatVisitor
- useTimestamp
- _useTimestampExplicitOnly
- Java 8 date time JSON formatting with Jackson
- Creating a POJO
- Controller Layer
- JUNIT 5 test at Controller layer for JSR-310 types
- Spring DateTimeFormat vs Jackson JsonFormat
- Github Repository
Jackson java time instant
Specific format to use, if not default format: non null value also indicates that serialization is to be done as JSON String, not numeric timestamp, unless _useTimestamp is true.
Flag that indicates that serialization must be done as the Java timestamp, regardless of other settings.
Fields inherited from class com.fasterxml.jackson.databind.ser.std.StdSerializer
Constructor Summary
Method Summary
Methods inherited from class com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializerBase
Methods inherited from class com.fasterxml.jackson.databind.ser.std.StdSerializer
Methods inherited from class com.fasterxml.jackson.databind.JsonSerializer
Methods inherited from class java.lang.Object
Field Detail
INSTANCE
_useTimestamp
Flag that indicates that serialization must be done as the Java timestamp, regardless of other settings.
_formatter
protected final java.time.format.DateTimeFormatter _formatter
Specific format to use, if not default format: non null value also indicates that serialization is to be done as JSON String, not numeric timestamp, unless _useTimestamp is true.
_shape
protected final com.fasterxml.jackson.annotation.JsonFormat.Shape _shape
Constructor Detail
InstantSerializer
protected InstantSerializer()
InstantSerializer
protected InstantSerializer(InstantSerializer base, Boolean useTimestamp, java.time.format.DateTimeFormatter formatter)
Method Detail
withFormat
protected com.fasterxml.jackson.datatype.jsr310.ser.JSR310FormattedSerializerBase withFormat(Boolean useTimestamp, java.time.format.DateTimeFormatter formatter, com.fasterxml.jackson.annotation.JsonFormat.Shape shape)
withFeatures
createContextual
public com.fasterxml.jackson.databind.JsonSerializer createContextual(com.fasterxml.jackson.databind.SerializerProvider prov, com.fasterxml.jackson.databind.BeanProperty property) throws com.fasterxml.jackson.databind.JsonMappingException
getSchema
acceptJsonFormatVisitor
public void acceptJsonFormatVisitor(com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper visitor, com.fasterxml.jackson.databind.JavaType typeHint) throws com.fasterxml.jackson.databind.JsonMappingException
useTimestamp
protected boolean useTimestamp(com.fasterxml.jackson.databind.SerializerProvider provider)
_useTimestampExplicitOnly
protected boolean _useTimestampExplicitOnly(com.fasterxml.jackson.databind.SerializerProvider provider)
How to convert Jackson deserialized ISO8601 formatted date-time into Java8 Instant
The Java 8 Instant class is used to record event time with relevance to UTC time zone.
You can pass ISO8601 formatted date-time or an date-time String value matching the pattern(“yyyy-MM-dd’T’HH:mm:ss.SSSZ”) or to de-serialize to an Instant value
In this tutorial, you will learn about Jackson’s way of De-serializing and Serializing ISO8601 formatted date-time into Java 8 Instant in detail.
Using LocalDateTime and Custom De-serializer
The Java LocalDateTIme can be used to represent ISO8601 formatted date-time.
Check this tutorial to convert a String to LocalDateTime, How to parse/format dates with Java 8 LocalDateTime
To Jackson’s way of De-serializing an ISO8601 formatted date-time into Instant,
- Create a De-serializer class that extends JsonDeserializer
- Override the de-serialize () method and extract the input value.
- Create a pattern( «yyyy-MM-dd HH:mm:ss» ) using DateTimeFormatter
- Use the LocalDateTime.parse(inputValue, formatter) method to convert the input value to the LocalDateTime value.
- Convert the LocalDateTime value to Instant using .toInstant(ZoneOffset.UTC) method, specifying the time-zone to UTC. Instant value is also created based on the UTC time zone.
Use this approach when the input string does not contain complete values matching the Instant ISO-8601 pattern(yyyy-MM-dd’T’HH:mm:ss.SSSZ). When time-zone information is not present in the input string then De-serializer should set the time-zone value to get Instant value
//Employee.java import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.techmam.javatutorials.Java8InstantDeserializer; import lombok.Data; import lombok.NoArgsConstructor; import java.time.Instant; @Data @NoArgsConstructor public class Employee < String name; @JsonDeserialize(using = Java8InstantDeserializer.class) Instant entryTime; Instant currentTime; > //Java8InstantDeserializer.java import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import java.io.IOException; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; public class Java8InstantDeserializer extends JsonDeserializer < @Override public Instant deserialize(JsonParser p, DeserializationContext ctxt) throws IOException < String inputText = p.getValueAsString(); Instant instant = LocalDateTime.parse(inputText, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")).toInstant(ZoneOffset.UTC); return instant; > > //EmployeeController.Java import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import java.time.Instant; @RestController public class EmployeeController < @PostMapping("/employee") public Employee createDetails(@RequestBody Employee employee) < employee.setCurrentTime(Instant.now()); return employee; >> //Request Body < "name":"Pandey", "entryTime":"2023-01-01 23:33:34" >
< "name": "Pandey", "entryTime": "2023-01-01T23:33:34Z", "currentTime": "2023-02-26T11:00:54.478958700Z" >
In the above example, the ISO-8601 format date time value is parsed to an Instant value and returned in the response body.
Using @JsonFormat()
The @Jsonformat annotation can be used to Serialize a property by specifying a pattern.
//Employee.java @Data @AllArgsConstructor public class Employee < String name; @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ", shape = JsonFormat.Shape.STRING) Instant entryTime; Instant currentTime; >//RequestBody
< "timestamp": "2023-02-25T21:11:05.677+0000", "status": 500, "error": "Internal Server Error", "trace": "org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Unsupported field: YearOfEra; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Unsupported field: YearOfEra. >
When you try to serialize a formatted Instant value, it throws a JSON: Unsupported field: YearOfEra exception, as Instant does not support YearOfEra type while writing the response.
To resolve the above issue, the Instant value needs to be serialized to String, as shown below,
- Create a new class for serializing Instant value which should extend JsonSerializer .
- The serializer class should override the serialize method and convert the Instant type value to String (InstantValue.toString()).
- Invoke the JsonGenerator.writeString(string) method to write the string value in the response.
- Use @JsonSerialize(using = Java8InstantSerializer.class) on the field level to serialize the Instant value.
//Employee.java public class Employee< String name; @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ", shape = JsonFormat.Shape.STRING) @JsonSerialize(using = Java8InstantSerializer.class) Instant entryTime; Instant currentTime; > //Java8InstantSerializer.java import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import java.io.IOException; import java.time.Instant; public class Java8InstantSerializer extends JsonSerializer < @Override public void serialize(Instant value, JsonGenerator gen, SerializerProvider serializers) throws IOException < gen.writeString(value.toString()); > > //RequestBody < "name":"Pandey", "entryTime":"2023-01-01T23:33:34Z" >
< "name": "Pandey", "entryTime": "2023-01-01T23:33:34Z", "currentTime": "2023-02-25T21:17:21.430702900Z" >
Related Topics
Jackson java time instant
Specific format to use, if not default format: non null value also indicates that serialization is to be done as JSON String, not numeric timestamp, unless _useTimestamp is true.
Flag that indicates that serialization must be done as the Java timestamp, regardless of other settings.
Fields inherited from class com.fasterxml.jackson.databind.ser.std.StdSerializer
Constructor Summary
Method Summary
Methods inherited from class com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializerBase
Methods inherited from class com.fasterxml.jackson.databind.ser.std.StdSerializer
Methods inherited from class com.fasterxml.jackson.databind.JsonSerializer
Methods inherited from class java.lang.Object
Field Detail
INSTANCE
_useTimestamp
Flag that indicates that serialization must be done as the Java timestamp, regardless of other settings.
_formatter
protected final java.time.format.DateTimeFormatter _formatter
Specific format to use, if not default format: non null value also indicates that serialization is to be done as JSON String, not numeric timestamp, unless _useTimestamp is true.
_shape
protected final com.fasterxml.jackson.annotation.JsonFormat.Shape _shape
Constructor Detail
InstantSerializer
protected InstantSerializer()
InstantSerializer
protected InstantSerializer(InstantSerializer base, Boolean useTimestamp, java.time.format.DateTimeFormatter formatter)
Method Detail
withFormat
protected com.fasterxml.jackson.datatype.jsr310.ser.JSR310FormattedSerializerBase withFormat(Boolean useTimestamp, java.time.format.DateTimeFormatter formatter, com.fasterxml.jackson.annotation.JsonFormat.Shape shape)
withFeatures
createContextual
public com.fasterxml.jackson.databind.JsonSerializer createContextual(com.fasterxml.jackson.databind.SerializerProvider prov, com.fasterxml.jackson.databind.BeanProperty property) throws com.fasterxml.jackson.databind.JsonMappingException
getSchema
acceptJsonFormatVisitor
public void acceptJsonFormatVisitor(com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper visitor, com.fasterxml.jackson.databind.JavaType typeHint) throws com.fasterxml.jackson.databind.JsonMappingException
useTimestamp
protected boolean useTimestamp(com.fasterxml.jackson.databind.SerializerProvider provider)
_useTimestampExplicitOnly
protected boolean _useTimestampExplicitOnly(com.fasterxml.jackson.databind.SerializerProvider provider)
Java 8 date time JSON formatting with Jackson
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.
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
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.
@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
Here we will just test the controller layer using JUNIT 5 based tests in Spring Boot.
@ExtendWith(SpringExtension.class) @WebMvcTest(DateController.class) class DateControllerTest < @Autowired private MockMvc mockMvc; @Test void postDate() throws Exception < //language=JSON String jsonPayload = ""; 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