When you are building REST web services using the Java 8 JDK, you might want to use the new Date & Time API to define temporal fields in your entity classes. For example, you might define the following simple User entity with the three fields username, fullname, and dateOfBirth:
import java.time.LocalDate;
public class User {
private String username;
private String fullname;
private LocalDate dateOfBirth;
// getters + setters...
}
An instance of this entity could be serialized as a JSON string in your REST service as follows:
{
username: "jane.doe",
fullname: "Jane Doe",
dateOfBirth: [
1986,
10,
06
]
}
When you try to consume such a web service with the Jackson mapper, for instance using Spring’s RestTemplate classes, you will experience the following exception:
com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class java.time.LocalDate]: can not instantiate from JSON object (need to add/enable type information?)
The problem here is that Jackson does not support the Java 8 Date & Time API out of the box, so you have to add this support yourself. But rest assured, adding this support is simple, as there is already a support library available from FasterXML: jackson-datatype-jsr310. To enable support for these new data types, you simply have to add the jackson-datatype-jsr310 support library to your classpath, for example with Maven:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.4.0</version>
</dependency>
Update: As Khaled correctly points out in the comments, you also need to explicitly tell the Jackson ObjectMapper to include support for JSR 310. In a Spring environment this could be achieved by the following bean definition (example courtesy of Khaled):
@Bean(name = "OBJECT_MAPPER_BEAN")
public ObjectMapper jsonObjectMapper() {
return Jackson2ObjectMapperBuilder.json()
.serializationInclusion(JsonInclude.Include.NON_NULL) // Don’t include null values
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) //ISODate
.modules(new JSR310Module())
.build();
}
If you’re like me, working with Spring Boot, you don’t need any explicit configuration, since this registration is automatically done for you by Spring Boot. But of course in a different environment, the Jackson ObjectMapper needs to be specifically set up.