我如何使用杰克逊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"])
当前回答
我想为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);
}
}
其他回答
如果您因为GraphQL Java工具而遇到此问题,并试图从日期字符串编组Java Instant,则需要设置SchemaParser以使用具有特定配置的ObjectMapper:
在GraphQLSchemaBuilder类中,注入ObjectMapper并添加以下模块:
ObjectMapper objectMapper =
new ObjectMapper().registerModule(new JavaTimeModule())
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
并将其添加到选项中:
final SchemaParserOptions options = SchemaParserOptions.newOptions()
.objectMapperProvider(fieldDefinition -> objectMapper)
.typeDefinitionFactory(new YourTypeDefinitionFactory())
.build();
参见https://github.com/graphql-java-kickstart/graphql-spring-boot/issues/32
这里不需要使用自定义序列化器/反序列化器。使用jackson-modules-java8的datetime模块:
数据类型模块,使Jackson识别Java 8日期和时间API数据类型(JSR-310)。
这个模块增加了对很多类的支持:
持续时间 即时 LocalDateTime LocalDate 本地时间 MonthDay OffsetDateTime OffsetTime 期 一年 YearMonth ZonedDateTime ZoneId ZoneOffset
如果你正在使用Spring引导,并且在OffsetDateTime上有这个问题,那么需要使用上面@greperror回答的registerModules(5月28日16日13:04回答),但注意有一个区别。不需要添加提到的依赖项,因为我猜spring boot已经有它了。我有这个问题与春季启动,它为我工作,没有添加这个依赖。
如果你正在使用Jackson Serializer,下面是一种使用date模块的方法:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import org.apache.kafka.common.serialization.Serializer;
public class JacksonSerializer<T> implements Serializer<T> {
private final ObjectMapper mapper = new ObjectMapper()
.registerModule(new ParameterNamesModule())
.registerModule(new Jdk8Module())
.registerModule(new JavaTimeModule());
@Override
public byte[] serialize(String s, T object) {
try {
return mapper.writeValueAsBytes(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
}
如果你考虑使用fastjson,你可以解决你的问题,注意版本
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
</dependency>