ジャクソンは、JavaでのLocalDateTime限りelasticsearchデシリアライズ8

グロッグ:

私たちは、日付フィールドが移入されていlongelasticsearchインデックスインチ

フィールドのマッピングは次のとおりです。

@Field(type = FieldType.Date)
@JsonFormat(shape = JsonFormat.Shape.NUMBER_INT)
private LocalDateTime created;

そして、私が使用Jackson JavaTimeModuleし、Jdk8Moduleこの構成では:

@Bean
public ElasticsearchOperations elasticsearchTemplate() {
   return new ElasticsearchRestTemplate(client(), new CustomEntityMapper());
}

public static class CustomEntityMapper implements EntityMapper {

        private final ObjectMapper objectMapper;

        public CustomEntityMapper() {
            //we use this so that Elasticsearch understands LocalDate and LocalDateTime objects
            objectMapper = new ObjectMapper()
                              .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
                              .configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true)
                              .configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, false)
                              .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
                              .configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false)
                              //MUST be registered BEFORE calling findAndRegisterModules
                              .registerModule(new JavaTimeModule())
                              .registerModule(new Jdk8Module());
            //only autodetect fields and ignore getters and setters for nonexistent fields when serializing/deserializing
            objectMapper.setVisibility(objectMapper.getSerializationConfig().getDefaultVisibilityChecker()
                            .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
                            .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
                            .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
                            .withCreatorVisibility(JsonAutoDetect.Visibility.NONE));
            //load the other available modules as well
            objectMapper.findAndRegisterModules();
        }

        @Override
        public String mapToString(Object object) throws IOException {
            return objectMapper.writeValueAsString(object);
        }

        @Override
        public <T> T mapToObject(String source, Class<T> clazz) throws IOException {
            return objectMapper.readValue(source, clazz);
        }
}

:しかし、私は、次のような分野で、インデックス内のエンティティを解析しようとすると、

"created" : 1563448935000

私はエラーを取得します:

com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (VALUE_NUMBER_INT), expected VALUE_STRING: Expected array or string.

私はそれをデシリアライズすることが可能である、と考えるlongまでに、私は、私が行方不明です何が表示されません。

私がそれをマップする場合Long、それはもちろん、作品と同じ値として記憶されている場合String、我々は中に適切にそれとフォーマットを形作ります@JsonFormatしかし、それは持っていることが可能であるlong->LocalDateTimeだけでなくて?

マイケルZiober:

ビルドへLocalDateTimeのエポックからのミリ秒から1970-01-01T00:00:00Z、我々は時間帯を必要とします。バージョンでは2.9.9ミリ秒が表示されたら、それは例外をスローします。

生のタイムスタンプ(1563448935000)には使用できませんjava.time.LocalDateTime:そのようなオフセットや時間帯など必要な追加情報(クラスのJavadocを参照してください)

しかし、我々は、デフォルトのタイムゾーンでこれを行うにしようとする私たちのデシリアライザを実装することができます。実装例は以下のようになります。

class MillisOrLocalDateTimeDeserializer extends LocalDateTimeDeserializer {

    public MillisOrLocalDateTimeDeserializer() {
        super(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
    }

    @Override
    public LocalDateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        if (parser.hasToken(JsonToken.VALUE_NUMBER_INT)) {
            long value = parser.getValueAsLong();
            Instant instant = Instant.ofEpochMilli(value);

            return LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
        }

        return super.deserialize(parser, context);
    }

}

ZoneOffset.UTC使用されている。あなたのケースでは、あなたはあなたまたは使用のシステムのデフォルトを提供することができます。使用例:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;

import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        // override default
        javaTimeModule.addDeserializer(LocalDateTime.class, new MillisOrLocalDateTimeDeserializer());

        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(javaTimeModule);

        String json = "{\"created\":1563448935000}";
        System.out.println(mapper.readValue(json, Created.class));

    }
}

class Created {

    private LocalDateTime created;

    // getters, setters, toString
}

上記のコードを印刷:

Created{created=2019-07-18T11:22:15}

EDIT:使用してJackson 2.9.0、ためのこの提供されたコードが呼び出されることはありません問題があるためfindAndRegisterModules、それを上書きしますカスタマイズされたモジュールを登録した後に呼び出されます。その呼び出しを削除すると、完全なシナリオの作業を行います。お使いのバージョンでは動作しません上記の場合は、デバッグのデフォルトの実装に必要と理由を見つけます。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=316598&siteId=1