杰克逊在反序列化到JodaTime时失去了与日期相关的时间

时间:2013-10-18 22:28:26

标签: java json jackson jodatime

我正在尝试使用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

3 个答案:

答案 0 :(得分:7)

是的,这是设计的。 JodaTime DateTimeSerializer使用标准的toString()方法。根据{{​​3}} toString()返回 - DateTime的标准ISO8601字符串。此外,标准DateTimeDeserializer始终创建UTC日期时间。

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

<强>更新

版本2.2.3有一些扩展行为 - DateTimeDeserializer使用从DeserializationContext获取的timeZone创建DateTime。可以使用ObjectMapper.setTimeZone()进行更改。默认值为TimeZone.getTimeZone("GMT")

答案 1 :(得分:7)

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

mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);

See this issue on GitHub

答案 2 :(得分:1)

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

  

根据毫秒即时,时间顺序 和时区 ,将此对象与指定对象进行相等性比较。 (我的重点)

     

两个代表同一时刻但在不同时区(基于时区ID)的对象将被视为不同。只有两个具有相同DateTimeZone,Chronology和instant的对象是相等的。

你展示的两个日期指的是同一时刻,但由于他们有不同的时区,JodaTime说他们不是“平等”。我没有看到杰克逊如何处理它们。