UGA Boxxx

つぶやきの延長のつもりで、知ったこと思ったこと書いてます

【Jackson】JavaのZonedDateTime型とESのdateタイプ(strict_date_time)のアンマッチ対策

Elasticsearchのあるインデックスにdateタイプのフィールドを定義し、そこにバッチの開始日時を格納していた

dateタイプで使っているフォーマットはstrict_date_time

        "startDateTime": {
          "type": "date",
          "format": "strict_date_time"
        },

strict_date_timeは日時のフォーマットが完璧なyyyy-MM-dd'T'HH:mm:ss.SSSZZの形でなくてはならない

Javaアプリケーション側では、そこにZonedDateTime型のプロパティを登録している

これで特に問題はないと思われたがたまにElasticsearch側でエラーが発生していた

エラーログは以下

ElasticsearchException[Elasticsearch exception [type=mapper_parsing_exception, reason=failed to parse field [startDateTime] of type [date]]]; nested: ElasticsearchException[Elasticsearch exception [type=illegal_argument_exception, reason=Invalid format: "2020-09-30T07:38:32Z" is malformed at "Z"]];

一見なにが問題かわからなかったが、どうやらyyyy-MM-dd'T'HH:mm:ss.SSSZZ.SSSの部分が欠けていて、フォーマットにあっていないようだった

おそらくSSSの部分が000で、トリムされた模様

対策

JacksonのObjectMapperを使ってESに登録する前にjsonシリアライズしているので、そこでZonedDateTime型に対してシリアライザを設定することにする

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(
            ZonedDateTime.class,
            new ZonedDateTimeSerializer(
                    DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX")
                            .withZone(ZoneId.of("UTC"))));
mapper.registerModule(module);
String json = mapper.writeValueAsString(hoge);

これで、.SSSの部分が欠けることなく登録することができるようになった