在春季使用RestTemplate将ISO日期字符串解析为ZoneDateTime [英] Parsing ISO Date String into ZoneDateTime with RestTemplate in Spring
问题描述
我正在通过RestTemplate发出GET请求,以获取一些包含dateCreated
字段的数据.日期/时间以以下格式存储为ISO标准字符串:
I am making a GET request through a RestTemplate to fetch some data which contains a dateCreated
field. The Date/Time is stored as an ISO Standard String in the following format:
2020-01-14T15:21:52.000+0530
但是,在此步骤中,RestTemplate在接收到该字符串时无法将其映射到 ZonedDateTime 对象:
However, the RestTemplate is unable to map this string to a ZonedDateTime Object on receiving it at this step:
ResponseEntity<OrderData[]> responseEntity = restTemplate.getForEntity(urlGETList, OrderData[].class);
但是,当将ISO字符串传递到Controller时,使用下面的objectMapper实现使用@RequestBody
将ISO字符串映射到 ZonedDateTime 时,类似的映射也可以正常工作
However, a similar mapping works fine when the ISO string is passed to a Controller which uses @RequestBody
to map the ISO String to ZonedDateTime using the following objectMapper implementation
@Bean
public ObjectMapper objectMapper() {
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(ZonedDateTime.class,
new ZonedDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX")));
return Jackson2ObjectMapperBuilder.json().featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) // ISODate
.modules(javaTimeModule).build();
}
在RestTemplate方法中,遇到以下错误
In the RestTemplate method, I encounter the following error
Caused by: java.lang.NoSuchFieldError: ACCEPT_CASE_INSENSITIVE_VALUES
at com.fasterxml.jackson.datatype.jsr310.deser.JSR310DateTimeDeserializerBase.acceptCaseInsensitiveValues(JSR310DateTimeDeserializerBase.java:126)
at com.fasterxml.jackson.datatype.jsr310.deser.JSR310DateTimeDeserializerBase.createContextual(JSR310DateTimeDeserializerBase.java:86)
at com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer.createContextual(InstantDeserializer.java:241)
at com.fasterxml.jackson.databind.DeserializationContext.handlePrimaryContextualization(DeserializationContext.java:651)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:484)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:293)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
at com.fasterxml.jackson.databind.DeserializationContext.findContextualValueDeserializer(DeserializationContext.java:444)
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.createContextual(ObjectArrayDeserializer.java:128)
at com.fasterxml.jackson.databind.DeserializationContext.handleSecondaryContextualization(DeserializationContext.java:682)
at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:482)
at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:4190)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4009)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3084)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:237)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:225)
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:95)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:917)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:901)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:655)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)
at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:312)
at com.increff.assure.service.ClientWrapper.getOrdersByChannel(ClientWrapper.java:111)
at com.increff.assure.dto.OrderDto.getByChannel(OrderDto.java:57)
at com.increff.assure.controller.ChannelOrderController.getByChannel(ChannelOrderController.java:42)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
... 43 more
是什么导致无法序列化ISO日期/时间字符串?
What is preventing the serializing the ISO Date/Time String?
推荐答案
问题是通过RestTemplate
接收的JSON无法弄清楚如何将接收到的ISO DateTime字符串解析为ZonedDateTime
对象.
The problem was that the JSON received through the RestTemplate
couldn't figure out how to parse the ISO DateTime String it received to a ZonedDateTime
object.
我找到了解决方案,方法是在ObjectMapper
中包含一个自定义 ZonedDateTimeDeserializer
以将ISO格式的字符串解析为ZonedDateTime
.尽管ZonedDateTimeSerializer
是预先提供和完全实现的,但我找不到ZonedDateTimeDeserialzer
.因此,我的自定义解串器可以解决这个问题
I found the solution by including a custom ZonedDateTimeDeserializer
in the ObjectMapper
to parse ISO format strings to ZonedDateTime
. Although a ZonedDateTimeSerializer
is pre-provided and fully implemented, I couldn't find a ZonedDateTimeDeserialzer
. So my custom deserializer takes care of that
public class ZonedDateTimeDeserializer extends JsonDeserializer<ZonedDateTime> {
@Override
public ZonedDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException {
return ZonedDateTime.parse(
jsonParser.getText(),
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX")
);
}
}
接下来,我将此反序列化器添加到我的ObjectMapper
中.
Next, I add this deserializer to my ObjectMapper
.
@Bean
public ObjectMapper objectMapper() {
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(ZonedDateTime.class,
new ZonedDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX")));
javaTimeModule.addDeserializer(ZonedDateTime.class,
new ZonedDateTimeDeserializer());
ObjectMapper objMapper = Jackson2ObjectMapperBuilder.json().featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) // ISODate
.modules(javaTimeModule).build();
return objMapper;
}
当完美使用RestTemplate
时,它可以处理ZonedDateTime
的解析.
This handles the parsing of ZonedDateTime
when using RestTemplate
perfectly.
这篇关于在春季使用RestTemplate将ISO日期字符串解析为ZoneDateTime的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!