将java.util.time.LocalDateTime反序列化为joda LocalDateTime

时间:2016-05-19 16:24:13

标签: java json jackson jodatime

我有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"])

我应该编写自己的杰克逊解串器,还是可以使用其他库/版本?

2 个答案:

答案 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());