Local Date, Local Time and Local DateTime are the time and date API s that Java 8 started to provide. They are mainly used to optimize the processing operations of time and date before Java 8. However, when we use Spring Boot or Spring Cloud Feign, we often find problems when we use request parameters or return results with LocalDate, LocalTime, LocalDateTime. In this paper, we will talk about the problems in this situation and how to solve them.
Problem phenomenon
Let's look at the symptoms first. For example, the following example:
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @RestController class HelloController { @PostMapping("/user") public UserDto user(@RequestBody UserDto userDto) throws Exception { return userDto; } } @Data @NoArgsConstructor @AllArgsConstructor static class UserDto { private String userName; private LocalDate birthday; } }
The above code builds a simple Spring Boot Web application that provides an interface for submitting user information, which contains data of Local Date type. At this point, if we use Feign to call this interface, we will get the following error:
2018-03-13 09:22:58,445 WARN [http-nio-9988-exec-3] org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver - Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Can not construct instance of java.time.LocalDate: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of java.time.LocalDate: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?) at [Source: java.io.PushbackInputStream@67064c65; line: 1, column: 63] (through reference chain: java.util.ArrayList[0]->com.didispace.UserDto["birthday"])
Analysis and solution
For the above error message JSON parse error: Can not construct instance of java.time.LocalDate: no suitable constructor found, can not deserialize from Object value, children's shoes familiar with Spring MVC should be able to locate the error immediately related to the deserialization of LocalDate. However, many readers will still be confused by the error message java.util.ArrayList [0] - > com.didispace.UserDto["birthday"]. We named the submitted UserDto["birthday"] as a LocalDate object. What does it have to do with the ArrayList list object?
We might as well send a request manually through postman and so on to see what the server returns. For example, you can make a request as follows:

From the above figure, we can understand the confusion I mentioned above. In fact, by default Spring MVC serializes the LocalDate into an array type, while Feign handles the invocation according to ArrayList, so naturally it is impossible to deserialize the LocalDate object.
Solution
To solve the above problem is very simple, because Jackson also provides a set of serialization solutions, we only need to introduce jackson-datatype-jsr310 dependency in pom.xml, as follows:
<dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> </dependency>
Note: It is not necessary to specify a specific version in the case of spring boot parent, nor is it recommended to specify a specific version.
This module encapsulates the implementation of Java 8's time and date API serialization, which is implemented in this class: com.fasterxml.jackson.datatype.jsr310.JavaTimeModule (Note: Some earlier versions go crazy in this class "com.fasterxml.jackson.datatype.jsr310.JSR310Module). After configuring dependencies, we only need to add this serialization module to the application main class above and disable the timestamp output feature for dates:
@Bean public ObjectMapper serializingObjectMapper() { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); objectMapper.registerModule(new JavaTimeModule()); return objectMapper; }
At this point, when we access the interface just now, we will no longer be an array type, and the call to the Feign client will no longer have the above errors.
First issue of this article: http://blog.didispace.com/Spring-Boot-And-Feign-Use-localdate/
Code example
For examples in this article, you can see the Chapter 3-1-7 directory in the following warehouse:
- Github: https://github.com/dyc87112/SpringBoot-Learning
- Gitee: https://gitee.com/didispace/SpringBoot-Learning
Spring Booot 2.0 features are being serialized. Click to see what the interpretations are.