1
votes

I am not able to deserialize OffsetDateTime in spring data elasticsearch when I am simply getting document from the cluster. There are some approaches how to solve the issue, but mostly valid for the previous versions of Spring boot. As well in the current snapshot release of spring-data-elasticsearch the jackson mapper is removed and replaced by some mapper class.

May somebody please give me a hint how to solve this properly with current version of boot + elastic 6.x/7.x ?

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.OffsetDateTime` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

I am using REST High level client.

Solution: Solved with custom entity mapper:

public class CustomEntityMapper implements EntityMapper {

    private final ObjectMapper objectMapper;

    public CustomEntityMapper() {

            JavaTimeModule javaTimeModule = new JavaTimeModule();
            javaTimeModule.addDeserializer(LocalDateTime.class, new MillisOrLocalDateTimeDeserializer());

            objectMapper = new ObjectMapper()
                                      .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
                                      .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
                                     .enable(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS)
                                      .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
                                      .registerModule(javaTimeModule)
            ;

            objectMapper.setVisibility(objectMapper.getSerializationConfig().getDefaultVisibilityChecker()
                            .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
                            .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
                            .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
                            .withCreatorVisibility(JsonAutoDetect.Visibility.NONE));

            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);
    }

    @Override
    public Map<String, Object> mapObject(Object source) {
        return null;
    }

    @Override
    public <T> T readObject(Map<String, Object> source, Class<T> targetType) {
        return null;
    }
}
1

1 Answers

0
votes

For Spring Data Elasticsearch 3.2 you will need to use a customized Jackson Mapper where you register corresponding modules.

From Spring Data Elasticsearch 4.0 on (currently available as milestone release 4.0.0.M3) OffsetDateTime can be written and read with a custom date format, it seems that OffsetDateTime is picky with parsing, I would have thought that the basic_date_time format should work, but I had to find a custom format string.

I just tried the following definition:

@Field(type=FieldType.Date, format=DateFormat.custom, pattern="uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSZ")

But as said, this would be for the upcoming version 4 of Spring Data Elasticsearch.