java - 这是 jackson-datatype-jsr310 反序列化器中的错误吗?

标签 java spring-data jsr310

我知道,想象在数千名开发人员每天使用的库中发现错误的想法是自以为是的。所以我认为我的标题问题的答案是“不!!!”,但是......

我有一个对象,其中包含从前端 (JS) 收到的日期,并将其存储到 MongoDB 数据库中。我使用 Spring 获取此对象(使用 REST Controller ),并使用 Spring 执行持久性(使用 MongoDBRepository)。我的计算机配置了 CEST 时钟,即 GMT+2 (UTC +0200)。

我的 POJO 中的日期存储在 LocalDateTime 中。

这是我的对象:

class Test{
  LocalDateTime when;
  String data;
  // getter setters...
}

以下单元测试显示 Spring(使用 jackson-jsr310)用 UTC 日期时间填充我的 LocalDateTime。

mockMvc.perform(post("/test")
        .contentType(MediaType.APPLICATION_JSON_UTF8)
        .content("{\"when\":\"2017-03-31T14:20:28.000Z\",\"data\":\"toto\"}")).andExpect(status().isOk());

List<com.robopec.models.Test> tests =  testRepository.findAll();
Assert.assertEquals(14, tests.get(0).getWhen().getHour());

我们可以在jackson源码中看到LocalDateTimeDeserializer.java第 74 行:

 return LocalDateTime.ofInstant(Instant.parse(string), ZoneOffset.UTC);

但是当我保存在数据库中时,spring 使用 spring-data-commons 将 LocalDateTime 转换为日期,然后再将日期存储在数据库中。 我们可以阅读spring-data-commons/../Jsr310Converters.java这:

public static enum LocalDateTimeToDateConverter implements Converter<LocalDateTime, Date> {
        INSTANCE;
        @Override
        public Date convert(LocalDateTime source) {
            return source == null ? null : Date.from(source.atZone(systemDefault()).toInstant());
        }
    }

因此,spring-data JSR310 转换器将 localdatetime 解释为默认系统区域中的瞬间。

问题是,当我的前端发送“2017-04-03T20:00:00Z”时,REST Controller 将其存储在 LocalDateTime 中,时间如下:20:00:00。当mongo-data转换器将其转换为日期时,得到的时间是20:00:00+0200(因为我的电脑处于CEST时区)。

我的结论是,我不应该将日期存储在 LocalDateTime 中,而应该存储在 Date (java.util) 或 Instant 中。

但是,其中一个转换器是否存在错误?

最佳答案

如果我没记错的话,最新版本的 mongoDB Java 驱动程序仍然使用 java.util.Date 来存储日期,因此使用 Java 8 时间 api 可能会有点麻烦。

在我从事的一个项目中,几个月前我从 Joda Datetime 切换到了 Java 8 时间。我无法使用 LocalDateTime、ZonedDateTime 等,因此我决定使用 Instant效果很好。只需记住对您的日期使用 ISO8601 Zulu 表示法(“2017-03-31T14:20:28.000Z”),这显然已经是您正在做的事情。

关于java - 这是 jackson-datatype-jsr310 反序列化器中的错误吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43194043/

相关文章:

java - 使用 ObjectMapper java API 解析 JSON 字符串

java - 从数组中删除重复项并写入文本文件

java - Java DateTime 中的 Duration.between() 返回负值时

java - 如何将包含 LocalDate 字段的 json 转换为可反序列化格式?

java - 想要使用数组元素作为属性,但引号会导致错误Java

Java 与 C# : BigInteger hex string yields different result?

spring-boot - Spring Data Redis - 存储库上的@Transactional 支持

java - Spring Data JPA 忽略 FetchMode

spring - 如何使用 Gradle 和 Spring Boot 来获取 Spring 数据的 Gosling Release Train?

java-8 - 证明 310 OffsetDate 类型合理的用例是什么?