diff --git a/java-client/src/main/java/co/elastic/clients/json/DelegatingJsonpMapper.java b/java-client/src/main/java/co/elastic/clients/json/DelegatingJsonpMapper.java index 708bd442a..09b6608ee 100644 --- a/java-client/src/main/java/co/elastic/clients/json/DelegatingJsonpMapper.java +++ b/java-client/src/main/java/co/elastic/clients/json/DelegatingJsonpMapper.java @@ -48,6 +48,11 @@ public void serialize(T value, JsonGenerator generator) { mapper.serialize(value, generator); } + @Override + public String serializeToString(T value) { + return mapper.serializeToString(value); + } + @Override public boolean ignoreUnknownFields() { return mapper.ignoreUnknownFields(); diff --git a/java-client/src/main/java/co/elastic/clients/json/JsonpMapper.java b/java-client/src/main/java/co/elastic/clients/json/JsonpMapper.java index a47992b9b..ed2629185 100644 --- a/java-client/src/main/java/co/elastic/clients/json/JsonpMapper.java +++ b/java-client/src/main/java/co/elastic/clients/json/JsonpMapper.java @@ -19,11 +19,14 @@ package co.elastic.clients.json; +import co.elastic.clients.json.jackson.JacksonJsonProvider; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; import jakarta.json.spi.JsonProvider; import jakarta.json.stream.JsonGenerator; import jakarta.json.stream.JsonParser; import javax.annotation.Nullable; +import java.io.StringWriter; /** * A {@code JsonpMapper} combines a JSON-P provider and object serialization/deserialization based on JSON-P events. @@ -51,6 +54,17 @@ public interface JsonpMapper { */ void serialize(T value, JsonGenerator generator); + /** + * Serialize an object to its JSON String representation + */ + default String serializeToString(T value) { + StringWriter writer = new StringWriter(); + try (JsonGenerator generator = jsonProvider().createGenerator(writer)) { + serialize(value, generator); + }; + return writer.toString(); + } + /** * Should object parsers in the API client be lenient and silently ignore unknown fields? * diff --git a/java-client/src/main/java/co/elastic/clients/json/JsonpMapperBase.java b/java-client/src/main/java/co/elastic/clients/json/JsonpMapperBase.java index 3f7e6b110..4763c8424 100644 --- a/java-client/src/main/java/co/elastic/clients/json/JsonpMapperBase.java +++ b/java-client/src/main/java/co/elastic/clients/json/JsonpMapperBase.java @@ -19,11 +19,15 @@ package co.elastic.clients.json; +import jakarta.json.JsonException; import jakarta.json.JsonValue; +import jakarta.json.spi.JsonProvider; import jakarta.json.stream.JsonGenerator; import jakarta.json.stream.JsonParser; import javax.annotation.Nullable; +import java.io.IOException; +import java.io.StringWriter; import java.lang.reflect.Field; public abstract class JsonpMapperBase implements JsonpMapper { @@ -76,6 +80,24 @@ public static JsonpSerializer findSerializer(T value) { return null; } + @Override + public String serializeToString(T value) { + JsonpSerializer serializer = findSerializer(value); + + if (serializer != null) { + StringWriter writer = new StringWriter(); + JsonGenerator generator = jsonProvider().createGenerator(writer); + serializer.serialize(value, generator, this); + generator.close(); + return writer.toString(); + } else { + throw new JsonException( + "Cannot find a serializer for type " + value.getClass().getName() + + ". Consider using a full-featured JsonpMapper" + ); + } + } + protected static class JsonpSerializableSerializer implements JsonpSerializer { @Override public void serialize(T value, JsonGenerator generator, JsonpMapper mapper) { diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/json/JsonDataTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/json/JsonDataTest.java index e9cfed2eb..e29f9b832 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/json/JsonDataTest.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/json/JsonDataTest.java @@ -20,6 +20,10 @@ package co.elastic.clients.elasticsearch.json; import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.Result; +import co.elastic.clients.elasticsearch.core.IndexResponse; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.core.search.TotalHitsRelation; import co.elastic.clients.elasticsearch.indices.CreateIndexRequest; import co.elastic.clients.json.DelegatingDeserializer; import co.elastic.clients.json.JsonData; @@ -40,6 +44,7 @@ import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; +import java.util.Collections; public class JsonDataTest extends Assert { @@ -125,4 +130,38 @@ public void testConvert() { assertEquals(JsonValue.ValueType.STRING, value.getValueType()); assertEquals("foo", ((JsonString)value).getString()); } + + @Test + public void testIndexResponse() { + IndexResponse resp = IndexResponse.of(r -> r + .index("foo") + .id("1") + .primaryTerm(1) + .seqNo(1) + .version(1) + .shards(s -> s.successful(1).failed(0).total(1)) + .result(Result.Created) + ); + + String json = new JacksonJsonpMapper().serializeToString(resp); + + assertEquals("{\"_id\":\"1\",\"_index\":\"foo\",\"_primary_term\":1,\"result\":\"created\",\"_seq_no\":1,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0},\"_version\":1}", json); + } + + @Test + public void testSearchResponse() { + SearchResponse resp = SearchResponse.searchResponseOf(r -> r + .took(10) + .shards(s -> s.successful(1).failed(0).total(1)) + .timedOut(false) + .hits(h -> h + .total(t -> t.value(0).relation(TotalHitsRelation.Eq)) + .hits(Collections.emptyList()) + ) + ); + + String json = new JacksonJsonpMapper().serializeToString(resp); + + assertEquals("{\"took\":10,\"timed_out\":false,\"_shards\":{\"failed\":0.0,\"successful\":1.0,\"total\":1.0},\"hits\":{\"total\":{\"relation\":\"eq\",\"value\":0},\"hits\":[]}}", json); + } }