我如何使用杰克逊JSON映射与Java 8 LocalDateTime?

jsonmappingexception:不能实例化类型[简单类型,java.time类]的值。LocalDateTime] from JSON字符串;没有单字符串构造函数/工厂方法(通过引用链:MyDTO["field1"]->SubDTO["date"])


当前回答

如果你因为任何原因不能使用jackson-modules-java8,你可以(反)序列化即时字段,只要使用@JsonIgnore和@JsonGetter和@JsonSetter:

public class MyBean {

    private Instant time = Instant.now();

    @JsonIgnore
    public Instant getTime() {
        return this.time;
    }

    public void setTime(Instant time) {
        this.time = time;
    }

    @JsonGetter
    private long getEpochTime() {
        return this.time.toEpochMilli();
    }

    @JsonSetter
    private void setEpochTime(long time) {
        this.time = Instant.ofEpochMilli(time);
    }
}

例子:

@Test
public void testJsonTime() throws Exception {
    String json = new ObjectMapper().writeValueAsString(new MyBean());
    System.out.println(json);
    MyBean myBean = new ObjectMapper().readValue(json, MyBean.class);
    System.out.println(myBean.getTime());
}

收益率

{"epochTime":1506432517242}
2017-09-26T13:28:37.242Z

其他回答

对于那些正在寻找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引导,并且在OffsetDateTime上有这个问题,那么需要使用上面@greperror回答的registerModules(5月28日16日13:04回答),但注意有一个区别。不需要添加提到的依赖项,因为我猜spring boot已经有它了。我有这个问题与春季启动,它为我工作,没有添加这个依赖。

ObjectMapper objectMapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.registerModule(new JavaTimeModule());

这对我很有效

如果你正在使用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;
    }
}

对于spring引导api:

@Configuration
public class JsonConfig {

    @Bean
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
        MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
        ObjectMapper mapper = new ObjectMapper();

        mapper.registerModule(new ParameterNamesModule())
                .registerModule(new Jdk8Module())
                .registerModule(new JavaTimeModule());

        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);// will remove value properties
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        jsonConverter.setObjectMapper(mapper);
        return jsonConverter;
    }
}

导入以下依赖项:

implementation 'com.fasterxml.jackson.core:jackson-core:2.13.0'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.0'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.0'