我们在elasticsearch索引中有一个日期字段,其中填充了一个长的。
字段映射为:
@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,它当然会起作用,如果值存储为String,并且我们在JsonFormat中正确地对其进行造型和格式化,它也会起作用。但是有没有可能长一点-
使用Instant
作为日期的Jackson字段类型。这简化了一切!您只需要注册模块:https://github.com/FasterXML/jackson-modules-java8
要从1970-01-01T00:00:00Z
时代的毫秒构建LocalDateTime
,我们需要一个时区。在2.9.9版中,当毫秒出现时它会引发异常:
原始时间戳(1563448935000)不允许java.time.LocalDateTime
:需要附加信息,例如偏移量或时区(参见类Javadocs)
但是我们可以实现我们的反序列化器,它将尝试使用默认时区执行此操作。示例实现如下所示:
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);
}
}
<代码>区域偏移。使用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}
编辑:使用Jackson 2.9.0,由于此问题,将不会调用提供的代码,因为注册自定义模块后调用的FindRegisterModules将覆盖它。删除该调用将使整个场景生效。如果以上内容不适用于您的版本,则需要调试默认实现并找到原因。
我刚刚根据新的(ish)Java8时间包将许多日期转换为LocalDateTime。到目前为止,我一直很喜欢这种转换,直到我开始尝试序列化和反序列化。 如何配置Jackson以支持他们?: LocalDateTime --serialize-- 这里有大量关于转换为格式化字符串的资料,但我似乎找不到utc时间戳的现成解决方案。
问题内容: 使用Jackson XmlMapper注释,如何将XML反序列化为pojo? 我试图使用这样的东西: 当我尝试使用XmlMapper的readValue()时,出现以下错误: 问题答案: 您的课程与您的课程不符。结构比您想象的要简单。请参见以下示例: 简单用法: 上面的程序打印(适用于您): 也可以看看: jackson-dataformat-xml。 主页:Jackson XML d
我有一个JSON字符串,它将空列表标记为而不是。因此,例如,如果我有一个没有子对象的对象,我将收到这样的字符串: 我想将其反序列化为父类,将子类正确设置为子类的空列表。 对于上面的JSON字符串,我想要一个将其id设置为13的对象,并将子元素设置为新的ArrayList 我知道如何为整个类使用注释 然后呢 但是,我想解决从字符串正确实例化列表的一般问题: 我能得到这样的东西吗?
我有一个具有两个属性的JSON对象:“key”(字符串)和“value”(可以反序列化为Java bean)。 问题是,给定一个这样的物体列表,我能把它反序列化为一张地图吗? 当前使用Jackson-databind 2.1
我想将json反序列化到类Foo: IBar有两个实现,但是当反序列化时,我总是想使用第一个实现。(理想情况下,这将使问题变得更容易,因为不需要运行时类型检查) 我相信我可以编写自定义反序列化程序,但我觉得一定有更简单的方法。 我找到了这个注释,它在没有列表的情况下非常有效。