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

Elastic Java Client:如何自定义JsonpMapper及用Fastjson替换JacksonJsonpMapper(ES7.16.2)

在Elasticsearch 7.16.2中自定义Elastic Java Client的JsonpMapper

一、自定义JsonpMapper的通用流程

JsonpMapper是Elastic Java Client用于对象与JSON互转的核心接口,默认实现为JacksonJsonpMapper。自定义它的通用步骤如下:

  • 实现/扩展JsonpMapper接口:
    你可以直接实现JsonpMapper接口,不过更高效的方式是继承AbstractJsonpMapper抽象类——它已经实现了大部分通用逻辑,只需重写序列化、反序列化的核心方法即可。
  • 配置客户端使用自定义Mapper:
    在构建ElasticsearchClient时,通过ElasticsearchClient.Builder的jsonpMapper()方法传入自定义的实现类实例。

二、用Fastjson替换默认JacksonJsonpMapper的具体实现

由于Fastjson没有官方提供JsonpMapper的实现,我们需要自行封装Fastjson的序列化逻辑,步骤如下:

1. 引入Fastjson依赖

如果使用Maven,在pom.xml中添加:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.83</version>
</dependency>

Gradle则添加:

implementation 'com.alibaba:fastjson:1.2.83'

2. 实现FastjsonJsonpMapper类

继承AbstractJsonpMapper,封装Fastjson的序列化/反序列化逻辑,同时处理Elasticsearch特定类型(如日期、GeoPoint)的自定义转换:

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.elasticsearch.client.json.AbstractJsonpMapper;
import org.elasticsearch.client.json.JsonpParser;
import org.elasticsearch.client.json.JsonpSerializable;
import org.elasticsearch.client.json.JsonpSerializer;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Type;

public class FastjsonJsonpMapper extends AbstractJsonpMapper {

    private final SerializerFeature[] serializerFeatures = {
            SerializerFeature.WriteDateUseDateFormat,
            SerializerFeature.DisableCircularReferenceDetect
    };

    private final Feature[] parserFeatures = {
            Feature.SupportAutoType
    };

    @Override
    public <T> T deserialize(JsonpParser parser, Type type) throws IOException {
        try (InputStream is = parser.inputStream()) {
            return JSON.parseObject(is, type, parserFeatures);
        }
    }

    @Override
    public void serialize(JsonpSerializable value, JsonpSerializer serializer, OutputStream out) throws IOException {
        if (value != null) {
            if (serializer != null) {
                serializer.serialize(value, this, out);
            } else {
                JSON.writeJSONString(out, value, serializerFeatures);
            }
        }
    }

    @Override
    public AbstractJsonpMapper withAttribute(String key, Object value) {
        FastjsonJsonpMapper mapper = new FastjsonJsonpMapper();
        mapper.attributes.putAll(this.attributes);
        mapper.attributes.put(key, value);
        return mapper;
    }
}

注意:如果需要处理Elasticsearch的特殊类型(如GeoPoint、Instant),可以为Fastjson添加对应的ObjectSerializer和ObjectDeserializer,并在构造方法中注册。

3. 配置ElasticsearchClient使用自定义Mapper

构建客户端时,传入FastjsonJsonpMapper实例:

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.transport.ElasticsearchTransport;
import org.elasticsearch.client.transport.rest_client.RestClientTransport;
import org.elasticsearch.client.ElasticsearchClient;

public class ElasticClientFactory {
    public static ElasticsearchClient createClient() {
        RestClient restClient = RestClient.builder(new HttpHost("localhost", 9200, "http")).build();
        FastjsonJsonpMapper customMapper = new FastjsonJsonpMapper();
        ElasticsearchTransport transport = new RestClientTransport(restClient, customMapper);
        return new ElasticsearchClient(transport);
    }
}

三、验证替换效果

可以通过简单的文档CRUD操作验证是否生效:

import java.io.IOException;

public class TestClient {
    public static void main(String[] args) throws IOException {
        ElasticsearchClient client = ElasticClientFactory.createClient();
        // 创建测试文档
        User user = new User("robin", 30);
        client.index(i -> i.index("users").id("1").document(user));
        // 查询文档并反序列化
        User fetchedUser = client.get(g -> g.index("users").id("1"), User.class);
        System.out.println(fetchedUser);
    }

    static class User {
        private String name;
        private Integer age;

        // 构造方法、getter、setter省略
        @Override
        public String toString() {
            return "User{" + "name='" + name + '\'' + ", age=" + age + '}';
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 00:32:39