Converting JsonData to Map in new ES Java Client

Hello everyone,

I'm working with the new Elasticsearch Java Client and need to convert a Hit 's _source (provided as JsonData ) into a Map<String, Object> . The previous Rest High-Level Client offered SearchHit.getSourceAsMap() , but I require a reliable equivalent in the new client for dynamic field access without POJOs.

Here's the problem:

Using hit.source().to(Map.class) within a loop processing TopHitsAggregate results, like:

// ... inside a loop processing TopHitsAggregate results
List<Map<String, Object>> hits = new ArrayList<>();
for (Hit<JsonData> hit : topHitsResult.hits().hits()) {
    assert hit.source() != null;
    Map<String, Object> mappingJson = hit.source().to(Map.class); // This line
    hits.add(populateProtectionField(mappingJson)); // populateProtectionField is a custom method
}

This approach causes unexpected type issues or incorrect deserialization for nested fields in the _source document. While hit.source().toMap() correctly provides a Map<String, Object> with nested structures, my ultimate goal is to simplify certain fields.

Sample Response :

{
  "display_name": {
    "chars": "Default Layer3 Section",
    "string": "Default Layer3 Section",
    "valueType": "STRING"
  }
}

Desired Final Output (Transformed Map<String, Object> ):

{
  "display_name": "Default Layer3 Section"
}

Could you confirm hit.source().toMap() is the correct and robust approach for the initial deserialization, and then advise on best practices for subsequently transforming a nested Map<String, Object> (like the one for display_name ) into a flattened structure as shown in my desired output? Insights into why hit.source().to(Map.class) is problematic for complex JSON are also appreciated! Thank you.

Hello!

hit.source().to(Map.class) is indeed the recommended way to convert JsonData into a Map.

For your specific case, you could provide a custom deserializer that would automatically parse the JsonData into the flattened map, by creating a custom implementation of JsonpDeserializer and then calling hit.source().deserialize(YourJsonpDeserializer<Map>), but considering the complexity and the fact that you'd have to hardcode the names of the fields in the deserializer anyways, I'd suggest simply iterating over the map and converting the values one by one to your desired output.

This approach causes unexpected type issues or incorrect deserialization for nested fields in the _source document

Could you provide an example of this? I've tried deserializing nested fields and I'm obtaining nested maps, as expected. Maybe working with POJOs could help, by making the nested fields more easily readable; you can create a custom class matching the output of sourceand then convert the JsonData like you do with the map, so hit.source().to(CustomClass.class, jsonpMapper) (where the jsonMapper is the same used to create the client).