web-dev-qa-db-ja.com

ZonedDateTimeのジャクソン逆シリアル化の問題

使用しているサービスの逆シリアル化中に使用するクラスに、次のフィールドがあります。

private ZonedDateTime transactionDateTime;

私が消費しているサービスは、次のパターンを使用してDateまたはDateTimeを返す場合があります。yyyy-MM-dd'T'HH:mm:ss.SSSZ

サービスが返すものの2つの例を挙げましょう:

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

前者は正常に機能しますが、後者では逆シリアル化中に次の例外がスローされます。

Java.time.format.DateTimeParseException:テキスト '2015-11-18T00:00:00.000 +0200'をインデックス23で解析できませんでした

私が使用しています。

  • Spring Boot 1.3.1
  • ジャクソン2.6.4(JSR310モジュールを含む)

これにはカスタムの逆シリアル化クラスが必要ですか?

8
tunix

コードの前半では、_@JsonFormat_アノテーション付きのフィールドを使用していましたが、JavaDocsが提案するように、シリアル化のみを目的としていると思ったので、それを削除しました。

その注釈を追加し直す必要があることが判明しました。そして本当の問題は、サードパーティのサービス応答が実際に間違っていた(XMLにラッパー要素がなかった)ため、逆シリアル化が失敗したことでした。エラーは次のとおりです。

com.fasterxml.jackson.databind.JsonMappingException:タイプ[単純なタイプ、クラスcom.foo.bar.adapter.john.model.account.UserAccount]の値を文字列値からインスタンス化できません( '2015-11-18T00:00: 00.000 + 0200 ');単一文字列のコンストラクタ/ファクトリメソッドはありません

フィールドは次のように記述されます。

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

また、オブジェクトはコレクションにラップされているため、このフィールドのクラスに@JsonRootName("transaction")を追加する必要がありました。

2
tunix

次のような注釈を使用できます。

@JsonSerialize(using = MyCustomJsonDateSerializer.class)

または

@JsonDeserialize(using = MyCustomJsonDateDeserializer.class)

ジャクソンが日付を解析する方法をカスタマイズします。これらのカスタムシリアライザーとデシリアライザーは、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);
      }
}
3
Ricardo Vila

jackson deserializeは、デフォルトでタイムゾーン情報をバイパスし、ctxタイムゾーンを使用してオーバーライドします。これにより、すべてのISO8601はUTCで終了します。

この機能は、春の春にいる場合はオフにすることができます。jackson.deserialization.ADJUST_DATES_TO_CONTEXT_TIME_ZONE= false

0
Jiajun Cui