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

Kre*_*sek 37 java datetime json 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")
Run Code Online (Sandbox Code Playgroud)

像这样:

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

但是,这些都不起作用,我得到一个例外:

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

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

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

Mei*_*mow 36

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

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

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

  • 谢谢,这对我帮助很大。我建议将毫秒部分设为可选: yyyy-MM-dd'T'HH:mm:ss[.SSS]XXX (4认同)
  • “Date”是可怕的遗留日期时间类的一部分,多年前已被现代 *java.time* 类取代。具体来说,“java.util.Date”被替换为“java.time.Instant”,即本问题中请求的类。 (3认同)
  • 为什么它对我来说失败了“无法构造 java.text.SimpleDateFormat 的实例,问题:非法模式字符“T””将类型更改为“Date”并保留“@JsonFormat(shape = JsonFormat.Shape.STRING)”帮助了我,感谢格斯的回答 (2认同)

小智 9

在 Jackson 2.9.8(我写这篇文章时的当前版本)中,最好使用 Instant 而不是 Date。

您必须添加一个依赖项:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.9.8</version>
</dependency> 
Run Code Online (Sandbox Code Playgroud)

此外,注册模块并将 SerializationFeature.WRITE_DATES_AS_TIMESTAMPS 配置为 false。

new ObjectMapper()
                .findAndRegisterModules()
                .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
Run Code Online (Sandbox Code Playgroud)

关于 Java8 的 Jackson 的更多信息:https : //github.com/FasterXML/jackson-modules-java8

  • 这调整了整个配置! (2认同)

Dim*_* II 8

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

ObjectMapper mapper = new ObjectMapper();
mapper.setDateFormat(new StdDateFormat().withColonInTimeZone(true));
Run Code Online (Sandbox Code Playgroud)

自版本 2.11 以来,默认的杰克逊时区格式已从“+0000”更改为“+00:00”。根据 ISO-8601,这两种格式都是有效的。


Gus*_*uss 5

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

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

[重点],您应该从上面的文本中了解到,指定shape = STRING将表示ISO-8601格式,但您可以使用该pattern属性选择其他内容。

以我的经验,这总是会显示UTC日期格式(时区显示为+0000),这可能是VM中的默认时区(即使我的操作系统时钟未设置为UTC)。

  • 我认为这个问题是关于反序列化,而不是序列化。但无论如何很高兴知道! (2认同)