我尝试使用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?
答案 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",不带冒号。
答案 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。