8

我正在尝试使用 Jackson 序列化然后反序列化 Joda DateTime 对象,但它并没有完全反序列化该对象。看起来时区信息丢失了。

这段代码:

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JodaModule());
mapper.configure(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS , false);

DateTime dt = DateTime.now();
String j = mapper.writeValueAsString(dt);
DateTime dt2 = mapper.readValue(j, DateTime.class);

System.out.println("json: " + j);
System.out.println("eq? " + (dt.equals(dt2)));
System.out.println("dates:\n" + dt + "\n" + dt2);

输出这个:

json: "2013-10-18T14:10:52.458-07:00"
eq? false
dates:
2013-10-18T14:10:52.458-07:00
2013-10-18T21:10:52.458Z

这是设计使然吗?除了编写自己的序列化器/反序列化器之外,我能在这里做些什么吗?我在 SO 上看到了一些关于此的问题,但没有一个专门针对此方面。

我正在使用 Joda 2.1 和 Jackson 2.1

4

3 回答 3

9

必须通过以下方式告知杰克逊不要将时区调整为当地情况:

mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);

在 GitHub 上查看此问题

于 2015-11-12T14:53:17.213 回答
8

是的,这是设计使然。JodaTimeDateTimeSerializer使用标准的 toString() 方法。根据JodaTime 官方指南 toString()返回 - DateTime 的标准 ISO8601 字符串。此外,标准DateTimeDeserializer始终创建 UTC 日期时间。

要存储 TimeZone,您需要将其与相同的 json 分开存储,并.withZone()在反序列化后使用方法,或者只创建序列化器和反序列化器。

更新

版本 2.2.3 有一点扩展行为 -DateTimeDeserializer创建 DateTime 时区取自DeserializationContext. 它可能会被改变ObjectMapper.setTimeZone()。默认为TimeZone.getTimeZone("GMT")

于 2013-10-18T23:13:40.410 回答
1

来自AbstractInstant#equals() 的 Javadoc,它是 的超类DateTime

根据毫秒瞬间、年表和时区比较此对象与指定对象的相等性。(我的重点)

表示同一时刻但位于不同时区(基于时区 id)的两个对象将被视为不同。只有具有相同 DateTimeZone、Chronology 和 Instant 的两个对象是相等的。

您显示的两个日期指定同一时刻,但由于它们有不同的时区,JodaTime 说它们不“相等”。我认为杰克逊的处理方式没有任何问题。

于 2013-10-18T23:11:33.733 回答