簡體   English   中英

ZonedDateTime 的 Jackson 反序列化問題

[英]Jackson deserialization issue for ZonedDateTime

我在反序列化我正在使用的服務期間使用的類中有以下字段。

private ZonedDateTime transactionDateTime;

我正在使用的服務可能會使用以下模式返回日期或日期時間: yyyy-MM-dd'T'HH:mm:ss.SSSZ

讓我舉兩個服務返回的例子:

  • 2015-11-18T18:05:38.000+0200
  • 2015-11-18T00:00:00.000+0200

雖然第一個運行良好,但后者會導致在反序列化過程中拋出以下異常:

java.time.format.DateTimeParseException:無法在索引 23 處解析文本“2015-11-18T00:00:00.000+0200”

我在用着;

  • 彈簧引導 1.3.1
  • Jackson 2.6.4(包含 JSR310 模塊)

這是否需要自定義反序列化類?

Jackson 反序列化將默認繞過時區信息並使用 ctx 時區覆蓋它,所有 ISO8601 將以 UTC 結束

這個功能可以關閉,如果你在春天

spring.jackson.deserialization.ADJUST_DATES_TO_CONTEXT_TIME_ZONE=false

您可以使用如下注釋:

@JsonSerialize(using = MyCustomJsonDateSerializer.class)

要么

@JsonDeserialize(using = MyCustomJsonDateDeserializer.class)

自定義 Jackson 解析日期的方式。 這些自定義序列化器和反序列化器必須擴展 JsonSerializer 和 JsonDeserializer。 例如:

public class MyCustomJsonDateSerializer extends JsonSerializer<Date> {

    @Override
    public void serialize(Date date, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
        jgen.writeString(date != null ? ISODateTimeFormat.dateTime().print(new DateTime(date)) : null);
      }
}

在代碼的前面,我使用了帶有@JsonFormat注釋的字段,但刪除了它,因為我認為它僅用於序列化,就像 JavaDocs 所建議的那樣。

原來我需要加回那個注釋。 真正的問題是第 3 方服務響應確實是錯誤的(它在 XML 中缺少包裝元素)導致反序列化失敗。 錯誤是:

com.fasterxml.jackson.databind.JsonMappingException: 無法從字符串值 ('2015-11-18T00:00: 00.000+0200'); 沒有單字符串構造函數/工廠方法

該字段如下所示:

@JsonFormat(pattern = Constants.DATETIME_FORMAT)
@JacksonXmlProperty(localName = "transactionDate")
private ZonedDateTime transactionDateTime;

此外,我還必須將@JsonRootName("transaction")添加到該字段的類中,因為該對象被包裝到一個集合中。

我用過

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssXXX")
private ZonedDateTime startDate;

顯然,加上jackson-datatype-jsr310庫。

Jackson deserialize ISO8601 formatted date-time into Java8 Instant中描述了此解決方案

以下配置幫助了我

指定日期時間模式:

public class Timestamp {

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssXXX")
    private ZonedDateTime timestamp;

}

禁止將 ZonedDateTime 轉換為 UTC:

objectMapper.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false);

還有另一個問題,可能很難發現。 在我的例子中,我使用 RestTemplate 從另一個微服務接收Timestamp RestTemplate 可以配置為使用notProjectDefaultObjectMapper ,它不受默認的 Spring Jackson 配置方法的影響(例如應用程序屬性,或帶有Jackson2ObjectMapperBuilderCustomizer bean 定義的@Configuration類或其他)。 所以RestTemplate 的 objectMapper(如果有的話)也應該被配置

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM