Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to Improve Deserialization of TasksRecord in Elasticsearch Java Client #896

Closed
Rodma1 opened this issue Oct 17, 2024 · 3 comments
Closed
Labels
Category: Question Not an issue but a question. May lead to enhancing docs

Comments

@Rodma1
Copy link

Rodma1 commented Oct 17, 2024


elsaticsearch: 8.11.4
elasticsearch-java: 8.11.4
java8

Issue: How to Improve Deserialization of TasksRecord in Elasticsearch Java Client

I am querying task records from Elasticsearch using the Java client like this:

List<TasksRecord> tasksRecords = client.cat().tasks().valueBody();

Currently, I am attempting to deserialize these TasksRecord objects into a Map using the following approach:

tasksRecords.forEach(item -> {
    String className = item.getClass().getSimpleName() + ": ";
    String replace = item.toString().replace(className, "");
    hashMaps.add(FastJsonUtils.toObject(replace));
});

In this code:

  1. I extract the string representation of each TasksRecord.
  2. Remove the class name prefix.
  3. Use FastJsonUtils.toObject() to deserialize the modified string into a Map.

I believe this solution is not ideal because it relies heavily on string manipulation, which can be error-prone and inefficient.

My main question is: How can I improve the deserialization process?

  • Is there a better way to directly deserialize TasksRecord into a Map or another structure, leveraging existing Elasticsearch client functionality?
  • How can I avoid manual string replacement and use a more efficient or standardized approach?

I would greatly appreciate any advice or best practices for optimizing this code.


@Rodma1 Rodma1 changed the title How to Convert Elasticsearch Java Client Query Results to Map<String, Object>? How to Improve Deserialization of TasksRecord in Elasticsearch Java Client Oct 17, 2024
@l-trotta
Copy link
Contributor

Hello! We have existing utilities to directly convert Elasticsearch client types to Maps, but we do have some other utilities that we can leverage to avoid string manipulation. Here's what I would to to convert a list of TaskRecords into a list of maps:

JacksonJsonpMapper jsonpMapper = new JacksonJsonpMapper(); // using Jackson mapper because it's the one we recommend

ElasticsearchTransport transport = new RestClientTransport(restClient, jsonpMapper); // restClient required of course

ElasticsearchClient esClient = new ElasticsearchClient(transport); //instance of the client

List<TasksRecord> taskList = esClient.cat().tasks().valueBody(); // getting the task records like you did

JsonProvider provider = JsonpUtils.provider(); // this is available from the client utilities, no need to import anything else

List<HashMap> maps = taskList.stream().map(task -> {
    StringWriter sw = new StringWriter(); // where the serialized json string will be written
    JsonGenerator generator = provider.createGenerator(sw); 

    task.serialize(generator,jsonpMapper); // this just outputs the json, no class name or other characters

    generator.close(); // flushing the buffer into the string writer

    return jsonpMapper.deserialize(jsonpMapper.jsonProvider().createParser(new StringReader(sw.toString())),HashMap.class); // deserializing the json string to a map
}).toList();

The result will be a List<Map<String,String>>. Hope this helps!

@l-trotta l-trotta added the Category: Question Not an issue but a question. May lead to enhancing docs label Oct 17, 2024
@Rodma1
Copy link
Author

Rodma1 commented Oct 18, 2024


Description:
I am trying to deserialize an IndexTemplateItem retrieved from Elasticsearch using the JacksonJsonpMapper, but I encounter the following error:

IllegalArgumentException: Jackson's ObjectMapper can only be used with the JacksonJsonpProvider

Code Snippet:

IndexTemplateItem indexTemplateItem = client.indices().getIndexTemplate(t -> t.name(indexTemplate)).indexTemplates().get(0);
JacksonJsonpMapper jsonpMapper = new JacksonJsonpMapper(); // Using Jackson mapper as recommended
StringWriter sw = new StringWriter(); // Where the serialized JSON string will be written
JsonProvider provider = JsonpUtils.provider(); // Available from the client utilities

JsonGenerator generator = provider.createGenerator(sw);
indexTemplateItem.serialize(generator, jsonpMapper); // Outputs the JSON

generator.close(); // Flushes the buffer into the string writer

return jsonpMapper.deserialize(jsonpMapper.jsonProvider().createParser(new StringReader(sw.toString())), HashMap.class); // Deserializing the JSON string to a map

Expected Behavior:
I expect to serialize the IndexTemplateItem into a JSON string and then deserialize it into a HashMap.

Actual Behavior:
The code throws an IllegalArgumentException indicating that the ObjectMapper can only be used with the JacksonJsonpProvider.

Additional Context:
I have ensured that I am using the JacksonJsonpMapper, but the issue persists.


Problem reporting error when serializing mapping parameters
Image

@l-trotta
Copy link
Contributor

Just replace

JsonProvider provider = JsonpUtils.provider();

with

JsonProvider provider = jsonpMapper.jsonProvider();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Category: Question Not an issue but a question. May lead to enhancing docs
Projects
None yet
Development

No branches or pull requests

2 participants