LocalDate, LocalTime, LocalDateTime are the time and date APIs provided by Java 8, which are mainly used to optimize the processing operations of time and dates in Java 8 before. However, when we use Spring Boot or Spring Cloud Feign, we often find that various problems will occur when using request parameters or returning results. In this article, we will talk about the problems that arise in this situation and how to solve them.
Problem phenomenon
Let’s take a look at the symptoms first. For example, the following example:
@SpringBootApplicationpublic 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, which provides an interface to submit user information, which contains data of LocalDate type. At this time, 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 and be related to the deserialization of LocalDate. However, there will still be many readers who will be confused by this error message java.util.ArrayList[0]->com.didispace.UserDto["birthday"] . UserDto["birthday"] we named and submitted is a LocalDate object. What does it have to do with the ArrayList list object?
We might as well send a request manually through postman or other information to see what the server returns? For example, you can make a request according to the following image:
From the above figure, we can understand the confusion I mentioned above. In fact, by default, Spring MVC serializes LocalDate into an array type, and when Feign is called, it still processes it according to ArrayList, so naturally it cannot be deserialized to a LocalDate object.
Solution
In order to solve the above problem, it is very simple, because jackson also provides a complete set of serialization solutions for this. We only need to introduce the jackson-datatype-jsr310 dependency in pom.xml, as follows:
<dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId></dependency>
Note: When the parent of spring boot is set, you do not need to specify a specific version, and it is not recommended to specify a specific version.
Encapsulate the implementation of Java 8's time-date API serialization in this module, and its specific implementation is in this class: com.fasterxml.jackson.datatype.jsr310.JavaTimeModule (Note: Some earlier versions are crazy about this class "com.fasterxml.jackson.datatype.jsr310.JSR310Module). After configuring the dependency, we only need to add this serialization module to the above application main class, and at the same time enable the standard ISO 8601 format:
@Beanpublic ObjectMapper serializingObjectMapper() { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); objectMapper.registerModule(new JavaTimeModule()); return objectMapper;}At this time, when we are accessing the interface just now, it is no longer an array type, and the above errors will no longer occur when we call Feign client.
Code Example
For relevant examples in this article, you can view the Chapter 3-1-7 directory in the following repository:
Github: https://github.com/dyc87112/SpringBoot-Learning
Gitee: https://gitee.com/diidispace/SpringBoot-Learning
Summarize
The above is the serialization problem of using Java 8 time and date API (LocalDate, etc.) in Spring Boot and Feign. I hope it will be helpful to everyone. If you have any questions, please leave me a message and the editor will reply to everyone in time. Thank you very much for your support to Wulin.com website!