Skip to content

Commit 17c94e0

Browse files
authored
support for withJson-618 (#1148)
* support for withJson-618 Signed-off-by: Jai2305 <[email protected]> * added code samples and documentation demonstrating the use of withJson Signed-off-by: Jai2305 <[email protected]> --------- Signed-off-by: Jai2305 <[email protected]>
1 parent b4f49c0 commit 17c94e0

File tree

10 files changed

+234
-5
lines changed

10 files changed

+234
-5
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ This section is for maintaining a changelog for all breaking changes for the cli
5353
- Added `queryImage` (query_image) field to `NeuralQuery`, following definition in ([Neural Query](https://opensearch.org/docs/latest/query-dsl/specialized/neural/)) ([#1137](https://github.com/opensearch-project/opensearch-java/pull/1138))
5454
- Added `cancelAfterTimeInterval` to `SearchRequest` and `MsearchRequest` ([#1147](https://github.com/opensearch-project/opensearch-java/pull/1147))
5555
- Added the `ml` namespace operations ([#1158](https://github.com/opensearch-project/opensearch-java/pull/1158))
56+
- Added `IndexTemplateMapping.Builder#withJson`, `SourceField.Builder#withJson` and `IndexSettings.Builder#withJson` for streamlining deserialization ([#1148](https://github.com/opensearch-project/opensearch-java/pull/1148))
5657

5758
### Dependencies
5859
- Bumps `commons-logging:commons-logging` from 1.3.3 to 1.3.4

guides/json.md

+43
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
- [Serialization](#serialization)
33
- [Using toJsonString](#using-tojsonstring)
44
- [Manual Serialization](#manual-serialization)
5+
- [Deserialization](#deserialization)
6+
- [Using withJson](#using-withjson)
7+
- [Using static _DESERIALIZER](#using-static-_deserializer)
58

69

710
# Working With JSON
@@ -50,4 +53,44 @@ private String toJson(JsonpSerializable object) {
5053
throw new UncheckedIOException(ex);
5154
}
5255
}
56+
```
57+
58+
## Deserialization
59+
60+
For demonstration let's consider an IndexTemplateMapping JSON String.
61+
62+
```java
63+
64+
String stringTemplate =
65+
"{\"mappings\":{\"properties\":{\"age\":{\"type\":\"integer\"}}},\"settings\":{\"number_of_shards\":\"2\",\"number_of_replicas\":\"1\"}}";
66+
```
67+
### Using withJson
68+
For classes, Builders of which implements `PlainDeserializable` interface, a default `withJson` method is provided.
69+
The withJson method returns the Builder enabling you to chain Builder methods for additional configuration.
70+
This implementation uses `jakarta.json.spi.JsonProvider` SPI to discover the available JSON provider instance
71+
from the classpath and to create a new mapper. The `JsonpUtils` utility class streamlines this deserialization process.
72+
The following code example demonstrates how to use the `withJson` method to deserialize objects:
73+
74+
```java
75+
InputStream inputStream = new ByteArrayInputStream(stringTemplate.getBytes(StandardCharsets.UTF_8));
76+
IndexTemplateMapping indexTemplateMapping = new IndexTemplateMapping.Builder().withJson(inputStream).build();
77+
```
78+
79+
80+
### Using static _DESERIALIZER
81+
For classes annotated with `@JsonpDeserializable`, a static field _DESERIALIZER is provided,
82+
which takes a mapper and a parser as arguments and returns the instance of the json value passed in the parser.
83+
Notice that this way you cannot further customize the instance, the state of which will solely depend on the json value parsed.
84+
85+
The following sample code demonstrates how to serialize an instance of a Java class:
86+
87+
```java
88+
private IndexTemplateMapping getInstance(String templateJsonString) {
89+
InputStream inputStream = new ByteArrayInputStream(templateJsonString.getBytes(StandardCharsets.UTF_8));
90+
JsonbJsonpMapper mapper = new JsonbJsonpMapper();
91+
try (JsonParser parser = mapper.jsonProvider().createParser(inputStream)) {
92+
IndexTemplateMapping indexTemplateMapping = new IndexTemplateMapping._DESERIALIZER.deserialize(parser, mapper);
93+
return indexTemplateMapping;
94+
}
95+
}
5396
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.client.json;
10+
11+
import jakarta.json.stream.JsonParser;
12+
import java.io.InputStream;
13+
import java.io.Reader;
14+
15+
/** Base interface to set JSON properties **/
16+
17+
public interface PlainDeserializable<B> {
18+
19+
B self();
20+
21+
/** Updates object with newly provided JSON properties
22+
@param parser the JsonParser parser
23+
@param mapper the JsonpMapper mapper used to deserialize values
24+
@return this object
25+
**/
26+
27+
default B withJson(JsonParser parser, JsonpMapper mapper) {
28+
JsonpDeserializer<?> deserializer = JsonpMapperBase.findDeserializer(this.getClass().getEnclosingClass());
29+
@SuppressWarnings("unchecked")
30+
ObjectDeserializer<B> objectDeserializer = (ObjectDeserializer<B>) DelegatingDeserializer.unwrap(deserializer);
31+
assert objectDeserializer != null;
32+
return objectDeserializer.deserialize(self(), parser, mapper, parser.next());
33+
}
34+
35+
/** Updates object with newly provided JSON properties
36+
@param inputStream the stream to read from
37+
@return this object
38+
* **/
39+
default B withJson(InputStream inputStream) {
40+
JsonpMapper defaultMapper = JsonpUtils.DEFAULT_JSONP_MAPPER;
41+
try (JsonParser parser = defaultMapper.jsonProvider().createParser(inputStream)) {
42+
return withJson(parser, defaultMapper);
43+
}
44+
}
45+
46+
/** Updates object with newly provided JSON properties
47+
@param reader the stream to read from
48+
@return this object
49+
* **/
50+
default B withJson(Reader reader) {
51+
JsonpMapper defaultMapper = JsonpUtils.DEFAULT_JSONP_MAPPER;
52+
try (JsonParser parser = defaultMapper.jsonProvider().createParser(reader)) {
53+
return withJson(parser, defaultMapper);
54+
}
55+
}
56+
57+
}

java-client/src/main/java/org/opensearch/client/opensearch/_types/mapping/SourceField.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.opensearch.client.json.JsonpMapper;
4242
import org.opensearch.client.json.ObjectBuilderDeserializer;
4343
import org.opensearch.client.json.ObjectDeserializer;
44+
import org.opensearch.client.json.PlainDeserializable;
4445
import org.opensearch.client.json.PlainJsonSerializable;
4546
import org.opensearch.client.util.ApiTypeHelper;
4647
import org.opensearch.client.util.ObjectBuilder;
@@ -172,7 +173,7 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) {
172173
* Builder for {@link SourceField}.
173174
*/
174175

175-
public static class Builder extends ObjectBuilderBase implements ObjectBuilder<SourceField> {
176+
public static class Builder extends ObjectBuilderBase implements ObjectBuilder<SourceField>, PlainDeserializable<Builder> {
176177
@Nullable
177178
private Boolean compress;
178179

@@ -263,6 +264,11 @@ public SourceField build() {
263264

264265
return new SourceField(this);
265266
}
267+
268+
@Override
269+
public Builder self() {
270+
return this;
271+
}
266272
}
267273

268274
// ---------------------------------------------------------------------------------------------

java-client/src/main/java/org/opensearch/client/opensearch/_types/mapping/TypeMapping.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.opensearch.client.json.JsonpMapper;
4444
import org.opensearch.client.json.ObjectBuilderDeserializer;
4545
import org.opensearch.client.json.ObjectDeserializer;
46+
import org.opensearch.client.json.PlainDeserializable;
4647
import org.opensearch.client.json.PlainJsonSerializable;
4748
import org.opensearch.client.util.ApiTypeHelper;
4849
import org.opensearch.client.util.ObjectBuilder;
@@ -363,7 +364,7 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) {
363364
* Builder for {@link TypeMapping}.
364365
*/
365366

366-
public static class Builder extends ObjectBuilderBase implements ObjectBuilder<TypeMapping> {
367+
public static class Builder extends ObjectBuilderBase implements ObjectBuilder<TypeMapping>, PlainDeserializable<Builder> {
367368
@Nullable
368369
private AllField allField;
369370

@@ -660,6 +661,11 @@ public TypeMapping build() {
660661

661662
return new TypeMapping(this);
662663
}
664+
665+
@Override
666+
public Builder self() {
667+
return this;
668+
}
663669
}
664670

665671
// ---------------------------------------------------------------------------------------------

java-client/src/main/java/org/opensearch/client/opensearch/indices/IndexSettings.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.opensearch.client.json.JsonpMapper;
4242
import org.opensearch.client.json.ObjectBuilderDeserializer;
4343
import org.opensearch.client.json.ObjectDeserializer;
44+
import org.opensearch.client.json.PlainDeserializable;
4445
import org.opensearch.client.json.PlainJsonSerializable;
4546
import org.opensearch.client.opensearch._types.Time;
4647
import org.opensearch.client.util.ApiTypeHelper;
@@ -1108,7 +1109,7 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) {
11081109
* Builder for {@link IndexSettings}.
11091110
*/
11101111

1111-
public static class Builder extends ObjectBuilderBase implements ObjectBuilder<IndexSettings> {
1112+
public static class Builder extends ObjectBuilderBase implements ObjectBuilder<IndexSettings>, PlainDeserializable<Builder> {
11121113
@Nullable
11131114
private IndexSettings index;
11141115

@@ -1919,6 +1920,10 @@ public final Builder knnAlgoParamEfSearch(@Nullable Integer value) {
19191920
return this;
19201921
}
19211922

1923+
@Override
1924+
public Builder self() {
1925+
return this;
1926+
}
19221927
}
19231928

19241929
// ---------------------------------------------------------------------------------------------

java-client/src/main/java/org/opensearch/client/opensearch/indices/put_index_template/IndexTemplateMapping.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.opensearch.client.json.JsonpMapper;
4242
import org.opensearch.client.json.ObjectBuilderDeserializer;
4343
import org.opensearch.client.json.ObjectDeserializer;
44+
import org.opensearch.client.json.PlainDeserializable;
4445
import org.opensearch.client.json.PlainJsonSerializable;
4546
import org.opensearch.client.opensearch._types.mapping.TypeMapping;
4647
import org.opensearch.client.opensearch.indices.Alias;
@@ -139,7 +140,7 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) {
139140
* Builder for {@link IndexTemplateMapping}.
140141
*/
141142

142-
public static class Builder extends ObjectBuilderBase implements ObjectBuilder<IndexTemplateMapping> {
143+
public static class Builder extends ObjectBuilderBase implements ObjectBuilder<IndexTemplateMapping>, PlainDeserializable<Builder> {
143144
@Nullable
144145
private Map<String, Alias> aliases;
145146

@@ -219,6 +220,11 @@ public IndexTemplateMapping build() {
219220

220221
return new IndexTemplateMapping(this);
221222
}
223+
224+
@Override
225+
public Builder self() {
226+
return this;
227+
}
222228
}
223229

224230
// ---------------------------------------------------------------------------------------------
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.client.opensearch.json;
10+
11+
import static org.junit.Assert.assertEquals;
12+
13+
import java.io.ByteArrayInputStream;
14+
import java.io.InputStream;
15+
import java.nio.charset.StandardCharsets;
16+
import java.util.Arrays;
17+
import java.util.List;
18+
import org.junit.Test;
19+
import org.opensearch.client.opensearch.indices.PutIndexTemplateRequest;
20+
import org.opensearch.client.opensearch.indices.put_index_template.IndexTemplateMapping;
21+
22+
public class PlainDeserializableTest {
23+
@Test
24+
public void testWithJsonPutIndexTemplateRequest() {
25+
26+
String stringTemplate =
27+
"{\"mappings\":{\"properties\":{\"age\":{\"type\":\"integer\"}}},\"settings\":{\"number_of_shards\":\"2\",\"number_of_replicas\":\"1\"}}";
28+
InputStream inputStream = new ByteArrayInputStream(stringTemplate.getBytes(StandardCharsets.UTF_8));
29+
30+
PutIndexTemplateRequest indexTemplateRequest = new PutIndexTemplateRequest.Builder().name("My index")
31+
.indexPatterns("index_pattern1")
32+
.template(new IndexTemplateMapping.Builder().withJson(inputStream).build())
33+
.build();
34+
35+
String expectedName = "My index";
36+
List<String> expectedIndexPatterns = Arrays.asList("index_pattern1");
37+
String expectedNumberOfShards = "2";
38+
39+
assertEquals(indexTemplateRequest.name(), expectedName);
40+
assertEquals(expectedIndexPatterns, indexTemplateRequest.indexPatterns());
41+
assertEquals(expectedNumberOfShards, indexTemplateRequest.template().settings().numberOfShards());
42+
43+
}
44+
}

java-client/src/test/java/org/opensearch/client/opensearch/json/PlainJsonSerializableTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public void testIndexResponse() {
5252

5353
// Test SearchRequest which implements PlainJsonSerializable
5454
@Test
55-
public void testSearchResponse() {
55+
public void testSearchRequest() {
5656

5757
String expectedStringValue =
5858
"{\"aggregations\":{},\"query\":{\"match\":{\"name\":{\"query\":\"OpenSearch\"}}},\"terminate_after\":5}";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.client.samples.json;
10+
11+
import java.io.ByteArrayInputStream;
12+
import java.io.InputStream;
13+
import java.nio.charset.StandardCharsets;
14+
import org.apache.logging.log4j.LogManager;
15+
import org.apache.logging.log4j.Logger;
16+
import org.opensearch.client.opensearch.OpenSearchClient;
17+
import org.opensearch.client.opensearch.indices.PutIndexTemplateRequest;
18+
import org.opensearch.client.opensearch.indices.PutIndexTemplateResponse;
19+
import org.opensearch.client.opensearch.indices.put_index_template.IndexTemplateMapping;
20+
import org.opensearch.client.samples.SampleClient;
21+
import org.opensearch.client.samples.Search;
22+
23+
public class DeserializationBasics {
24+
private static final Logger LOGGER = LogManager.getLogger(Search.class);
25+
26+
private static OpenSearchClient client;
27+
28+
public static void main(String[] args) {
29+
try {
30+
client = SampleClient.create();
31+
32+
var version = client.info().version();
33+
LOGGER.info("Server: {}@{}.", version.distribution(), version.number());
34+
35+
final var indexTemplateName = "my-index";
36+
37+
// Use Json String/File for storing template.
38+
String stringTemplate =
39+
"{\"mappings\":{\"properties\":{\"age\":{\"type\":\"integer\"}}},\"settings\":{\"number_of_shards\":\"2\",\"number_of_replicas\":\"1\"}}";
40+
// Create Input Stream for the above json template
41+
InputStream inputStream = new ByteArrayInputStream(stringTemplate.getBytes(StandardCharsets.UTF_8));
42+
43+
// Create Index Template Request for index 'my-index'.
44+
PutIndexTemplateRequest putIndexTemplateRequest = new PutIndexTemplateRequest.Builder().name(indexTemplateName)
45+
.template(new IndexTemplateMapping.Builder().withJson(inputStream).build()) // Use the Builder.withJson method to
46+
// deserialize the inputStream into an instance
47+
// of the IndexTemplateMapping class.
48+
.build();
49+
50+
LOGGER.info("Creating index template {}.", indexTemplateName);
51+
52+
// Use toJsonString method to log Request and Response string.
53+
LOGGER.debug("Index Template Request: {}.", putIndexTemplateRequest.toJsonString());
54+
PutIndexTemplateResponse response = client.indices().putIndexTemplate(putIndexTemplateRequest);
55+
LOGGER.info("Index Template Response: {}.", response.toJsonString());
56+
57+
} catch (Exception e) {
58+
LOGGER.error("Exception occurred.", e);
59+
}
60+
}
61+
}

0 commit comments

Comments
 (0)