杰克逊将日期时间的ISO8601反序列化为Java8 Instant

时间:2016-03-27 20:55:59

标签: java json datetime jackson java-8

我尝试使用Jackson将ISO8601格式的日期反序列化为Java8 Instant。我用ObjectMapper注册了JavaTimeModule,关闭了WRITE_DATES_AS_TIMESTAMPS。

但是,如果有人试图反序列化2016-03-28T19:00:00.000 + 01:00它将无效,因为似乎JavaTimeModule只会反序列化用UTC时区偏移量格式化的日期时间(例如2016-03- 28T18:00:00.000Z)。然后我尝试使用@JsonFormat注释:

@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss.SSSZ", timezone = "UTC")

就像这样:

@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss.SSSZ", timezone = JsonFormat.DEFAULT_TIMEZONE)

然而,这些都不起作用,我得到例外:

com.fasterxml.jackson.databind.JsonMappingException: Unsupported field: YearOfEra (through reference chain: org.example.Article["date"])

这意味着时区参数被忽略,日期时间格式化程序不知道如何在没有时区的情况下格式化Instant。

有没有办法在没有编写自定义反序列化程序的情况下,使用Jackson和JavaTimeModule将不在UTC时区偏移的ISO8601字符串反序列化为Java 8 Instant?

5 个答案:

答案 0 :(得分:27)

您需要在modell类中通过XXX设置显式时区:

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX")
private Date date;

(见:https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

答案 1 :(得分:2)

格式" Z"不适用于" +01:00"因为这是一种不同的模式。 JsonFormat正在使用SimpleDateFormat模式。 " Z"在大写中仅表示严格的RFC 822.您必须使用如下语法:" + 0100",不带冒号。

请参阅:ISO 8601:2004SimpleDateFormat patterns

答案 2 :(得分:2)

如果要将disable对象序列化为ISO-8601,则完全不需要指定模式-ISO-8601是默认模式。 JsonFormat Java doc中提到了这种情况:

  

常见用法包括在其他表示形式之间进行选择-例如,将Date序列化为数字(Java时间戳)还是字符串(例如与ISO-8601兼容的时间值)-使用pattern()属性配置确切的详细信息。

[强调我的内容],您应该从上面的文本中了解到,指定BooleanBinding表示ISO-8601格式,但是您可以使用Date属性选择其他内容。

根据我的经验,这总是会产生UTC日期格式(时区显示为shape = STRING),它可能是VM中的默认时区(即使我的操作系统时钟未设置为UTC)。

答案 3 :(得分:1)

在Jackson 2.9.8(我正在撰写本文时为当前版本)中,最好使用Instant而不是Date。

您必须添加一个依赖项:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.9.8</version>
</dependency> 

还要注册模块,并将SerializationFeature.WRITE_DATES_AS_TIMESTAMPS配置为false。

new ObjectMapper()
                .findAndRegisterModules()
                .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

有关Java8杰克逊的更多信息,请点击此处:https://github.com/FasterXML/jackson-modules-java8

答案 4 :(得分:1)

Jackson可以全局配置(不带注释)以接受带或不带冒号的时间戳记:

ObjectMapper mapper = new ObjectMapper();
mapper.setDateFormat(new StdDateFormat().withColonInTimeZone(true));

从版本2.11开始,默认的杰克逊时区格式已从“ +0000”更改为“ +00:00”。两种格式均符合ISO-8601。