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

Deserialization of java.util.time.LocalDateTime to joda LocalDateTime

我有 REST 网络服务公开资源和创建日期。它是用 Java 8 编写的 - 使用 LocalDateTime。 Jackson 2 正在将其序列化为:

"createdDate": [2016, 5, 19, 18, 6, 59, 639000000]

在其他应用程序中我的目标是消耗这个休息,但只有 Java 7,所以我决定在 DTO 中使用 joda-time 库。我已经像这样设置了 RestTemplate:

        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);

POST 成功,但是在反序列化答案时(使用上面的 createdDate 字段)抛出异常:

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

我的依赖项如下所示:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>3.2.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc-portlet</artifactId>
        <version>3.2.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>3.2.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>joda-time</groupId>
        <artifactId>joda-time</artifactId>
        <version>2.9.3</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-joda</artifactId>
        <version>2.7.4</version>
    </dependency>

我应该编写自己的 Jackson 解串器还是可以使用其他 library/version?

我相信 Jackson 将 Java 8 个时间类型与 nanosecond precision by default, while Joda-Time only supports milliseconds. What you'd need in your server written in Java 8 is to serialize the LocalDateTime 属性 序列化为 "createdDate": [2016, 5, 19, 18, 6, 59, 639] 而不是 "createdDate": [2016, 5, 19, 18, 6, 59, 639000000].

您可以在 Java 8 服务器中更改此行为,方法是配置您用于序列化的 ObjectMapper 实例:

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 supports it at the moment (see implementation)。因此,我认为您现在唯一的选择是实现自定义反序列化器,或者更好的是,提交对 joda 模块进行改进的 PR。

我已经解决了我的问题。这是我在服务器上的新杰克逊配置(而不是使用默认配置):

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