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

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


当前回答

这个maven依赖将解决你的问题:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.13.4</version>
</dependency>

我一直在挣扎的一件事是,在反序列化期间,ZonedDateTime时区被更改为GMT。 结果,Jackson默认用上下文中的一个替换它。 要保留区域1,必须禁用此“功能”

Jackson2ObjectMapperBuilder.json()
    .featuresToDisable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)

其他回答

@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
private LocalDateTime createTime;

这对我来说很有效。

如果有人在使用SpringBoot时遇到问题,这里是我在不添加新的依赖项的情况下修复问题的方法。

在Spring 2.1.3中,Jackson期望在此yyyy-MM-dd HH:mm:ss中出现日期字符串2019-05-21T07:37:11.000。在LocalDateTime中反序列化SSS格式。确保日期字符串用T分隔日期和时间,而不是用空格。秒(ss)和毫秒(SSS)可以省略。

@JsonProperty("last_charge_date")
public LocalDateTime lastChargeDate;

对于那些正在寻找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>

如果您正在使用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>>() {
            });

所有你需要知道的都在杰克逊文档里 https://www.baeldung.com/jackson-serialize-dates

9号广告很快为我解决了这个问题。

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);