Solve the serialization problem of using Java 8 time date API (LocalDate, etc.) in Spring Boot and Feign, feignlocaldate
LocalDate, LocalTime, and LocalDateTime are the time and date APIs provided by Java 8. They are mainly used to optimize the processing operations on time and date before Java 8. However, when we use Spring Boot or Spring Cloud Feign, we often find that there are various problems when we use the request parameters or when the returned results contain LocalDate, LocalTime, and LocalDateTime. This article describes the problems in this situation and how to solve them.
Symptom
Let's take a look at the symptoms. For 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 constructs a simple Spring Boot Web application, which provides an interface for submitting user information. User information contains LocalDate data. If Feign is used to call this interface, the following error is returned:
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 messageJSON parse error: Can not construct instance of java.time.LocalDate: no suitable constructor found, can not deserialize from Object value
, The children's shoes familiar with Spring MVC should be able to locate the error immediately and it is related to the deserialization of LocalDate. However, there will still be many readers who will receive this error message.java.util.ArrayList[0]->com.didispace.UserDto["birthday"]
Confused. We name the submittedUserDto["birthday"]
Is it a LocalDate object? What is the relationship with the ArrayList object?
We may try to manually send a request such as postman to see what the server returns? For example, you can initiate a request:
From this, we can understand the confusions I mentioned above. In fact, Spring MVC serializes LocalDate into an array type by default, and Feign still processes it according to ArrayList when calling it, therefore, it is naturally impossible to deserialize A LocalDate object.
Solution
To solve the problem above is very simple, because jackson also provides a complete serialization solution for this, we only need to introduce jackson-datatype-jsr310 dependencies in pom. xml, as shown below:
<dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId></dependency>
Note: you do not need to specify a specific version when setting the spring boot parent. You are not recommended to specify a specific version.
This module encapsulates the implementation of Java 8 time-date API serialization. The specific implementation is in this class: com. fasterxml. jackson. datatype. jsr310.JavaTimeModule (Note: some earlier versions go crazy to "com. fasterxml. jackson. datatype. jsr310.JSR310Module ). After the dependency is configured, we only need to add this serialization module to the main class of the preceding application and 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 point, the interface we just accessed is no longer an array type, and the above error will no longer occur when calling the Feign client.
Sample Code
The related examples in this article can view the Chapter3-1-7 directory in the following warehouse:
Github: https://github.com/dyc87112/SpringBoot-Learning
Gitee: https://gitee.com/didispace/SpringBoot-Learning
Summary
The above section describes how to solve the serialization problem of the Java 8 time date API (LocalDate, etc.) in Spring Boot and Feign. I hope it will be helpful to you, if you have any questions, please leave a message and the editor will reply to you in time. Thank you very much for your support for the help House website!