我们在elasticsearch索引中使用long
填充了一个日期字段。
字段Map为:
@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
反序列化为日期,但我不知道我错过了什么。
如果我把它Map到Long
,它当然可以工作,如果值存储为String
,我们在@JsonFormat
中正确地塑造和格式化它,它也可以工作。
3条答案
按热度按时间8fq7wneg1#
要从
1970-01-01T00:00:00Z
的历元开始以毫秒构建LocalDateTime
,我们需要一个时区。在2.9.9版本中,当毫秒出现时,它会抛出异常:原始时间戳(1563448935000)不允许用于
java.time.LocalDateTime
:需要额外的信息,如偏移量或时区(请参见Javadocs类)但是我们可以实现我们的反序列化器,它将尝试使用默认时区来执行此操作。示例实现如下所示:
使用
ZoneOffset.UTC
。在您的情况下,您可以提供您的或使用系统默认值。示例用法:以上代码打印:
编辑:使用
Jackson 2.9.0
,由于this问题,提供的代码将不会被调用,因为在注册自定义模块后调用的findAndRegisterModules
将覆盖它。删除该调用将使整个场景正常工作。如果以上不适用于您的版本,您需要调试默认实现并找到原因。l7mqbcuq2#
使用
Instant
作为日期的Jackson字段类型。这简化了一切!您只需要注册模块:https://github.com/FasterXML/jackson-modules-java8gz5pxeao3#
我想将一个时间戳反序列化为一个Long到一个Instant,并这样做: