我有REST webservice,用创建日期公开资源。它是用Java 8编写的 - 使用LocalDateTime。杰克逊2将其序列化为:
[0, 6, 12, 18]
在其他应用程序中,我的目标是使用其余的,但只有Java 7,所以我决定在DTO中使用joda-time库。我已经设置了RestTemplate:
"createdDate": [2016, 5, 19, 18, 6, 59, 639000000]
POST成功,但是在反序列化回答(使用上面的createdDate字段)时会抛出异常:
RestTemplate restTemplate = new RestTemplate();
MappingJackson2HttpMessageConverter e = new MappingJackson2HttpMessageConverter();
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JodaModule());
e.setObjectMapper(mapper);
messageConverters.add(e);
restTemplate.setMessageConverters(messageConverters);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<NewUserData> request = new HttpEntity<>(user, headers);
我的依赖关系如下所示:
org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Value 696000000 for millisOfSecond must be in the range [0,999] (through reference chain: com.foobar.dto.user.UserItem["createdDate"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Value 696000000 for millisOfSecond must be in the range [0,999] (through reference chain: com.foobar.dto.user.UserDisplayItem["createdDate"])
我应该编写自己的杰克逊解串器,还是可以使用其他库/版本?
答案 0 :(得分:1)
我相信Jackson默认使用nanosecond精度序列化Java 8时态类型,而Joda-Time仅支持milliseconds。您在Java 8中编写的服务器所需要的是将LocalDateTime
属性序列化为"createdDate": [2016, 5, 19, 18, 6, 59, 639]
而不是"createdDate": [2016, 5, 19, 18, 6, 59, 639000000]
。
您可以通过配置用于序列化的ObjectMapper
实例来更改Java 8服务器中的此行为:
ObjectMapper mapper = ... //this is the instance used to serialize the data
mapper.disable(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS);
如果您不能或不想更改Java 8服务器,Jackson会有相应的DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS
标志。遗憾的是,我认为joda module目前不支持它(见implementation)。因此,我认为你现在唯一的选择是实现自定义反序列化器,或者更好的是,提交一个改进了joda模块的PR。
答案 1 :(得分:0)
我已经解决了我的问题。这是我在服务器上的新jackson配置(而不是使用默认值):
private MappingJackson2HttpMessageConverter customMappingJackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.setDateFormat(new ISO8601DateFormat());
objectMapper.registerModule(new JavaTimeModule());
jsonConverter.setObjectMapper(objectMapper);
return jsonConverter;
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(customMappingJackson2HttpMessageConverter());
}
注册模块,禁止将日期写为时间戳并注册JavaTimeModule完成了这项工作。由于这个原因,服务器序列化日期为:
"createdDate":"2016-06-07T15:15:25"
在客户端应用程序中,我不得不更改jackson配置:
mapper.setDateFormat(new ISO8601DateFormat());