You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 2.7.6整合ElasticSearch时java.time.Instant反序列化失败

Spring Boot 2.7.6 集成 Elasticsearch Java Client 8.5.1 时 Instant 字段反序列化失败问题解决

问题描述

Spring Boot 2.7.6(基于JDK17)项目中,使用Elasticsearch Java Client 8.5.1查询数据时,实体类中的Instant字段无法正常反序列化,抛出如下错误:

2022-12-07 00:43:14.442 ERROR 59384 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[.[dispatcherServlet]      : Servlet.service() for servlet [dispatcherServlet] in context with path [/api/v1] threw exception [Request processing failed; nested exception is co.elastic.clients.json.JsonpMappingException: Error deserializing co.elastic.clients.elasticsearch.core.GetResponse: jakarta.json.JsonException: Jackson exception (JSON path: _source) (line no=1, column no=280, offset=-1)] with root cause

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type `java.time.Instant` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling
 at [Source: (org.apache.http.nio.entity.ContentInputStream); line: 1, column: 279] (through reference chain: test.com.model.Project["createdDate"])
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67) ~[jackson-databind-2.14.1.jar:2.14.1]
    at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1909) ~[jackson-databind-2.14.1.jar:2.14.1]
    at com.fasterxml.jackson.databind.deser.impl.UnsupportedTypeDeserializer.deserialize(UnsupportedTypeDeserializer.java:48) ~[jackson-databind-2.14.1.jar:2.14.1]
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129) ~[jackson-databind-2.14.1.jar:2.14.1]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:314) ~[jackson-databind-2.14.1.jar:2.14.1]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:177) ~[jackson-databind-2.14.1.jar:2.14.1]
    at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:323) ~[jackson-databind-2.14.1.jar:2.14.1]
    at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:4706) ~[jackson-databind-2.14.1.jar:2.14.1]
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2879) ~[jackson-databind-2.14.1.jar:2.14.1]
    at co.elastic.clients.json.jackson.JacksonJsonpMapper$JacksonValueParser.deserialize(JacksonJsonpMapper.java:123) ~[elasticsearch-java-8.5.1.jar:na]
    at co.elastic.clients.json.JsonpDeserializer.deserialize(JsonpDeserializer.java:76) ~[elasticsearch-java-8.5.1.jar:na]
    at co.elastic.clients.json.JsonpMapperBase.deserialize(JsonpMapperBase.java:70) ~[elasticsearch-java-8.5.1.jar:na]
    at co.elastic.clients.json.JsonpDeserializer$1.deserialize(JsonpDeserializer.java:99) ~[elasticsearch-java-8.5.1.jar:na]
    at co.elastic.clients.json.NamedDeserializer.deserialize(NamedDeserializer.java:64) ~[elasticsearch-java-8.5.1.jar:na]
    at co.elastic.clients.json.ObjectDeserializer$FieldObjectDeserializer.deserialize(ObjectDeserializer.java:78) ~[elasticsearch-java-8.5.1.jar:na]
    at co.elastic.clients.json.ObjectDeserializer.deserialize(ObjectDeserializer.java:192) ~[elasticsearch-java-8.5.1.jar:na]
    at co.elastic.clients.json.ObjectDeserializer.deserialize(ObjectDeserializer.java:148) ~[elasticsearch-java-8.5.1.jar:na]
    at co.elastic.clients.json.JsonpDeserializer.deserialize(JsonpDeserializer.java:76) ~[elasticsearch-java-8.5.1.jar:na]
    at co.elastic.clients.json.ObjectBuilderDeserializer.deserialize(ObjectBuilderDeserializer.java:79) ~[elasticsearch-java-8.5.1.jar:na]
    at co.elastic.clients.json.DelegatingDeserializer$SameType.deserialize(DelegatingDeserializer.java:43) ~[elasticsearch-java-8.5.1.jar:na]
    at co.elastic.clients.json.DelegatingDeserializer$SameType.deserialize(DelegatingDeserializer.java:43) ~[elasticsearch-java-8.5.1.jar:na]
    at co.elastic.clients.transport.endpoints.EndpointWithResponseMapperAttr$1.deserialize(EndpointWithResponseMapperAttr.java:56) ~[elasticsearch-java-8.5.1.jar:na]
    at co.elastic.clients.transport.rest_client.RestClientTransport.decodeResponse(RestClientTransport.java:325) ~[elasticsearch-java-8.5.1.jar:na]
    at co.elastic.clients.transport.rest_client.RestClientTransport.getHighLevelResponse(RestClientTransport.java:295) ~[elasticsearch-java-8.5.1.jar:na]
    at co.elastic.clients.transport.rest_client.RestClientTransport.performRequest(RestClientTransport.java:148) ~[elasticsearch-java-8.5.1.jar:na]
    at co.elastic.clients.elasticsearch.ElasticsearchClient.get(ElasticsearchClient.java:831) ~[elasticsearch-java-8.5.1.jar:na]
    at co.elastic.clients.elasticsearch.ElasticsearchClient.get(ElasticsearchClient.java:847) ~[elasticsearch-java-8.5.1.jar:na]
...
.....

已尝试无效的方案

最初以为Spring Boot默认的Jackson配置能处理Java 8时间类型,后来参考资料编写了Jackson配置类,但问题依旧:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.openapitools.jackson.nullable.JsonNullableModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

@Configuration
public class JacksonConfiguration {

    private final ObjectMapper objectMapper;

    public JacksonConfiguration(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Bean
    public JavaTimeModule dateTimeModule(){
        return new JavaTimeModule();
    }

    @PostConstruct
    ObjectMapper jacksonObjectMapper() {
        objectMapper.registerModule(new JavaTimeModule());
        objectMapper.registerModule(new JsonNullableModule());
        return objectMapper;
    }
}

问题原因

Elasticsearch Java Client(8.x版本)使用的是独立的JacksonJsonpMapper,而非Spring容器中管理的ObjectMapper。所以之前对Spring容器内ObjectMapper的配置,不会作用于Elasticsearch客户端的序列化逻辑。

解决方案

1. 确认依赖正确性

确保jackson-datatype-jsr310依赖已添加,且版本与jackson-databind一致(你的项目中已满足,版本均为2.14.1):

implementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-jsr310', version: '2.14.1'

2. 自定义ElasticsearchClient配置,注入带JavaTimeModule的ObjectMapper

创建Elasticsearch客户端配置类,手动初始化带有JavaTimeModule的JacksonJsonpMapper,并以此构建ElasticsearchClient:

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ElasticsearchConfig {

    @Bean
    public ElasticsearchClient elasticsearchClient() {
        // 初始化RestClient,替换为你的ES地址
        RestClient restClient = RestClient.builder(
                new HttpHost("localhost", 9200, "http")
        ).build();

        // 配置ObjectMapper,注册JavaTimeModule处理Instant等Java 8时间类型
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new JavaTimeModule());
        // 如果需要处理空值字段,可添加JsonNullableModule
        // objectMapper.registerModule(new JsonNullableModule());

        // 构建自定义的JacksonJsonpMapper
        JacksonJsonpMapper jsonpMapper = new JacksonJsonpMapper(objectMapper);

        // 初始化Transport和ElasticsearchClient
        RestClientTransport transport = new RestClientTransport(restClient, jsonpMapper);
        
        return new ElasticsearchClient(transport);
    }
}

3. 清理依赖冲突

你的项目中同时引入了elasticsearch-rest-high-level-client:7.17.6和elasticsearch-java:8.5.1,跨大版本依赖会引发兼容性问题。建议移除elasticsearch-rest-high-level-client依赖,Elasticsearch Java Client 8.x已完全替代它的功能。

验证

重启项目后,再次执行Elasticsearch查询,Instant字段应能正常反序列化,不再抛出错误。

内容的提问来源于stack exchange,提问作者MetaCoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 03:46:13