This is not the first time I have encountered Elastic clients returning different data formats, but this one is just truly baffling.

The Java API serializes its information with "typed keys" so that it can deserialize its own data internally. These types keys do not match any results from any other client making the same call: i.e. a direct Curl to the elastic server OR the javascript client.

Being able to do this:

ElasticsearchClient esClient = ...
// Create a new mapper with the typed_keys feature disabled
JsonpMapper mapper = esClient._jsonpMapper()
    .withAttribute(JsonpMapperFeatures.SERIALIZE_TYPED_KEYS, false);

StringWriter writer = new StringWriter();
try (JsonGenerator generator = mapper.jsonProvider().createGenerator(writer)) {
    mapper.serialize(searchResponse, generator);
}
String result = writer.toString();

// The aggregation only provides the "price" name
assertTrue(result.contains("\"aggregations\":{\"price\":{\"value\":3.14}}}"));

was not back ported to the 7.17.x line until 7.17.5. If you were using a client library older than that one (7.17.3 in our case) you could not use the Java API as a middleman for your frontend without changing the receving code to know about this new format. What should have been a simple endpoint change for the frontend would now require a priori knowledge about who they were calling and what format was coming back. You could not hot swap between a direct REST call, the javascript client, or a wrapper of this Java API.

There was not a lot of documentation on this online. I assume most implementations were walled gardens and did not cross over often.