我如何使用杰克逊JSON映射与Java 8 LocalDateTime?
jsonmappingexception:不能实例化类型[简单类型,java.time类]的值。LocalDateTime] from JSON字符串;没有单字符串构造函数/工厂方法(通过引用链:MyDTO["field1"]->SubDTO["date"])
我如何使用杰克逊JSON映射与Java 8 LocalDateTime?
jsonmappingexception:不能实例化类型[简单类型,java.time类]的值。LocalDateTime] from JSON字符串;没有单字符串构造函数/工厂方法(通过引用链:MyDTO["field1"]->SubDTO["date"])
当前回答
如果你正在使用Jersey,那么你需要像其他人建议的那样添加Maven依赖项(jackson- dattype -jsr310),并像这样注册你的对象映射器实例:
@Provider
public class JacksonObjectMapper implements ContextResolver<ObjectMapper> {
final ObjectMapper defaultObjectMapper;
public JacksonObjectMapper() {
defaultObjectMapper = createDefaultMapper();
}
@Override
public ObjectMapper getContext(Class<?> type) {
return defaultObjectMapper;
}
private static ObjectMapper createDefaultMapper() {
final ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
return mapper;
}
}
当在你的资源中注册Jackson时,你需要像这样添加这个映射器:
final ResourceConfig rc = new ResourceConfig().packages("<your package>");
rc
.register(JacksonObjectMapper.class)
.register(JacksonJaxbJsonProvider.class);
其他回答
我在使用Spring boot时遇到了类似的问题。 使用Spring启动1.5.1。我所要做的就是添加依赖项:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
如果您正在使用fastxml的ObjectMapper类, 默认情况下,ObjectMapper不理解LocalDateTime类,所以,你需要在你的gradle/maven中添加另一个依赖项:
compile 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.7.3'
现在你需要将这个库提供的数据类型支持注册到你的objectmapper对象中,这可以通过以下方式完成:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.findAndRegisterModules();
现在,在你的jsonString中,你可以很容易地把你的java。LocalDateTime字段如下所示:
{
"user_id": 1,
"score": 9,
"date_time": "2016-05-28T17:39:44.937"
}
通过这样做,你的Json文件到Java对象的转换将工作良好,你可以通过以下方式读取文件:
objectMapper.readValue(jsonString, new TypeReference<List<User>>() {
});
对于那些正在寻找ES-8和Spring Boot:3.0版本的解决方案的人
创建一个扩展ElasticsearchConfiguration的配置文件,并覆盖clientConfiguration和elasticsearchClient的创建。
在创建elasticsearchClient期间,注入您自己的配置为使用Java 8时间模块的objectMapper,它将覆盖默认的objectMapper。
@Override
public ClientConfiguration clientConfiguration() {
return ClientConfiguration.builder()
.connectedTo(<Hostname> +":"+ <Port>)
.usingSsl()
.withBasicAuth(<Username>, <Password>)
.build();
}
@Override
public ElasticsearchClient elasticsearchClient(RestClient restClient) {
Assert.notNull(restClient, "restClient must not be null");
//Create Java8 time module
JavaTimeModule module = new JavaTimeModule();
module.addSerializer(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DateFormat.date_time_no_millis.getPattern())));
//Register the module with objectMapper
ObjectMapper objectMapper=new ObjectMapper()
.registerModule(module);
//To convert datetime to ISO-8601
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
//Creating our own jsonpMapper
JsonpMapper jsonpMapper=new JacksonJsonpMapper(objectMapper);
// Create the transport with a Jackson mapper
ElasticsearchTransport transport = new RestClientTransport(
restClient, jsonpMapper);
// And create the API client
return new ElasticsearchClient(transport);
}
Maven的依赖:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.14.0</version>
</dependency>
我想为Spring的DurationStyle解析提供支持,在使用Jackson反序列化的自定义配置文件中的属性文件中提供支持,例如将20s序列化为Duration PT20S。我通过在ObjectMapper实例上注册一个自定义反序列化器来实现这一点:
@Bean("customConfigMapper")
public ObjectMapper customConfigMapper() {
final ObjectMapper mapper = new ObjectMapper();
final SimpleModule module = new SimpleModule();
module.addDeserializer(Duration.class, new SpringDurationStyleDeserializer());
mapper.registerModule(module);
return mapper;
}
public static class SpringDurationStyleDeserializer extends JsonDeserializer<Duration> {
@Override
public Duration deserialize(JsonParser jsonParser, DeserializationContext __) throws IOException {
return Optional.ofNullable(jsonParser.getText()).map(DurationStyle::detectAndParse).orElse(null);
}
}
您可以在应用程序中设置此参数。yml文件解析即时时间,即java8中的Date API:
spring.jackson.serialization.write-dates-as-timestamps=false