Jackson:用时区 ID 解析 ZonedDateTime

pio*_*rek 3 java spring-mvc jackson spring-boot java-time

使用Spring MVC(Spring boot)我可以ZonedDateTime反序列化

2016-07-26T05:30:47+01:00
Run Code Online (Sandbox Code Playgroud)

但不是来自

2016-07-26T05:30:47+01:00 Europe/Paris
Run Code Online (Sandbox Code Playgroud)

如何显式添加时区并且仍然能够反序列化它?

小智 6

您可以指定带有可选部分(由 分隔)的模式[],以指示某些字段是可选的,并使用@JsonFormat注释将其添加到相应的字段。

例如,学习这门课:

public class OptionalTimeZoneTest {

    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ssXXX[ VV]")
    private ZonedDateTime date;

    // getter and setter
}
Run Code Online (Sandbox Code Playgroud)

请注意最后一部分 ( [ VV]):里面的模式[]是可选部分,因此解析器会尝试解析它(如果存在)。模式VV是区域 ID(或时区名称;有关更多详细信息,请查看javadoc

这样,两种格式都可以读取:

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
// add this to preserve the same offset (don't convert to UTC)
mapper.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false);

// without timezone
String json = "{ \"date\": \"2016-07-26T05:30:47+01:00\" }";
OptionalTimeZoneTest value = mapper.readValue(json, OptionalTimeZoneTest.class);
System.out.println(value.getDate()); // 2016-07-26T05:30:47+01:00

// with timezone
json = "{ \"date\": \"2016-07-26T05:30:47+01:00 Europe/Paris\" }";
value = mapper.readValue(json, OptionalTimeZoneTest.class);
System.out.println(value.getDate()); // 2016-07-26T05:30:47+02:00[Europe/Paris]
Run Code Online (Sandbox Code Playgroud)

输出是:

2016-07-26T05:30:47+01:00
2016-07-26T05:30:47+02:00[欧洲/巴黎]

请注意,在第一种情况下,输出是2016-07-26T05:30:47+01:00(因为它没有时区,所以+01:00应用了偏移量)。

但在第二种情况下,输出为2016-07-26T05:30:47+02:00[Europe/Paris],因为在Europe/Paris时区中,26/07/2016 是夏季时间(因此偏移量为+02:00)。APIjava.time的实现方式是在解析此类String.


如果您希望所有ZonedDateTime实例都转换为 UTC,您可以删除此行:

mapper.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false);
Run Code Online (Sandbox Code Playgroud)

如果没有它,日期将转换为 UTC,输出将是:

2016-07-26T04:30:47Z[UTC]
2016-07-26T03:30:47Z[UTC]