这是jackson-datatype-jsr310解串器中的错误吗? [英] Is it a bug in jackson-datatype-jsr310 deserializer?

查看:612
本文介绍了这是jackson-datatype-jsr310解串器中的错误吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道图像的冒昧是在成千上万的开发人员每天使用的库中发现了一个错误。所以我认为我的标题问题的答案是NO !!!,但是......

I know that's presumptuous to image found a bug in a library used every day by thousands of developpers. So I think the answer to my title question is "NO !!!", but ...

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

I have an object containing a date that I receive from my front end (JS), and I store it into a MongoDB database. I use Spring to get this object (with a REST Controller), and Spring to perform persistance (with a MongoDBRepository). My computer is configured with a CEST clock, so GMT+2 (UTC +0200).

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

The date in my POJO is stored in a LocalDateTime.

这是我的对象:

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

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

The following unit test show that Spring (which use jackson-jsr310) fill my LocalDateTime with an UTC Date Time.

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行:

We can see in the jackson source code LocalDateTimeDeserializer.java line 74 :

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

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

But when I save in my database, spring use spring-data-commons to convert my LocalDateTime to a Date before storing the date in the database. We can read in spring-data-commons/../Jsr310Converters.java this :

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解释为默认系统区域中的瞬间。

So, spring-data JSR310 Converters interpret a localdatetime as an instant in the default system zone.

问题是当我的前端发送2017-04-03T20:00:00Z时,REST控制器将其存储在具有以下时间的LocalDateTime:20:00:00。当mongo-data转换器将其转换为日期时,结果时间为20:00:00 + 0200(因为我的计算机处于CEST时区)。

The problem is that when my front end send "2017-04-03T20:00:00Z", the REST controller store it in a LocalDateTime with the following time : 20:00:00. And when the mongo-data converter convert it into a date, the resulting time is 20:00:00+0200 (because my computer is in CEST time zone).

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

My conclusion is that I shouldn't store my date in a LocalDateTime but rather in a Date (java.util) or in an Instant.

但是,是其中一个转换器有错误吗?

推荐答案

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

If I remember correctly, the latest version of the Java driver for mongoDB still use java.util.Date to store dates, so using the Java 8 time api can be a bit of a hassle.

在我工作的一个项目中,几个月前我从Joda Datetime切换到Java 8时间。我无法使用LocalDateTime,ZonedDateTime等等,所以我决定使用即时,它工作正常。请记住在您的日期(2017-03-31T14:20:28.000Z)使用ISO8601 Zulu表示法,这已经是您正在做的事情。

In one project I work on, I switched from Joda Datetime to the Java 8 time a few months ago. I couldn't get my way around with LocalDateTime, ZonedDateTime and so on, so I decided to go with Instant and it worked fine. Just remember to use the ISO8601 Zulu notation for your dates ("2017-03-31T14:20:28.000Z"), which is already what you're doing apparently.

这篇关于这是jackson-datatype-jsr310解串器中的错误吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆