Skip to content

Commit 6e824d0

Browse files
Limit the size of toString() to a configurable limit (#272) (#273)
Co-authored-by: Sylvain Wallez <[email protected]>
1 parent 63feb66 commit 6e824d0

File tree

2 files changed

+78
-5
lines changed

2 files changed

+78
-5
lines changed

java-client/src/main/java/co/elastic/clients/json/JsonpUtils.java

+55-5
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import jakarta.json.stream.JsonParsingException;
3333

3434
import javax.annotation.Nullable;
35-
import java.io.IOException;
3635
import java.io.StringReader;
3736
import java.io.Writer;
3837
import java.util.AbstractMap;
@@ -242,15 +241,51 @@ public static void serializeIntOrNull(JsonGenerator generator, int value, int de
242241
}
243242
}
244243

244+
/**
245+
* Renders a <code>JsonpSerializable</code> as a string by serializing it to JSON. Any object of an application-specific
246+
* class in the object graph is rendered using that object's <code>toString()</code> representation as a JSON string value.
247+
* <p>
248+
* The size of the string is limited to {@link #MAX_TO_STRING_LENGTH}.
249+
*
250+
* @see #MAX_TO_STRING_LENGTH
251+
*/
245252
public static String toString(JsonpSerializable value) {
246253
return toString(value, ToStringMapper.INSTANCE, new StringBuilder()).toString();
247254
}
248255

256+
/**
257+
* Maximum length of the <code>toString</code> representation of a <code>JsonpSerializable</code>.
258+
* <p>
259+
* The default is 10k characters, and can be changed globally by changing the value of this field.
260+
*/
261+
public static int MAX_TO_STRING_LENGTH = 10000;
262+
263+
private static class ToStringTooLongException extends RuntimeException {
264+
}
265+
266+
/**
267+
* Renders a <code>JsonpSerializable</code> as a string in a destination <code>StringBuilder</code>by serializing it to JSON.
268+
* <p>
269+
* The size of the string is limited to {@link #MAX_TO_STRING_LENGTH}.
270+
*
271+
* @return the <code>dest</code> parameter, for chaining.
272+
* @see #toString(JsonpSerializable)
273+
* @see #MAX_TO_STRING_LENGTH
274+
*/
249275
public static StringBuilder toString(JsonpSerializable value, JsonpMapper mapper, StringBuilder dest) {
250276
Writer writer = new Writer() {
277+
int length = 0;
251278
@Override
252-
public void write(char[] cbuf, int off, int len) throws IOException {
253-
dest.append(cbuf, off, len);
279+
public void write(char[] cbuf, int off, int len) {
280+
int max = MAX_TO_STRING_LENGTH;
281+
length += len;
282+
if (length > max) {
283+
dest.append(cbuf, off, len - (length - max));
284+
dest.append("...");
285+
throw new ToStringTooLongException();
286+
} else {
287+
dest.append(cbuf, off, len);
288+
}
254289
}
255290

256291
@Override
@@ -263,11 +298,26 @@ public void close() {
263298
};
264299

265300
JsonGenerator generator = mapper.jsonProvider().createGenerator(writer);
266-
value.serialize(generator, mapper);
267-
generator.close();
301+
try {
302+
value.serialize(generator, mapper);
303+
generator.close();
304+
} catch (ToStringTooLongException e) {
305+
// Ignore
306+
}
268307
return dest;
269308
}
270309

310+
/**
311+
* Renders a <code>JsonpSerializable</code> as a string in a destination <code>StringBuilder</code>by serializing it to JSON.
312+
* Any object of an application-specific class in the object graph is rendered using that object's <code>toString()</code>
313+
* representation as a JSON string value.
314+
* <p>
315+
* The size of the string is limited to {@link #MAX_TO_STRING_LENGTH}.
316+
*
317+
* @return the <code>dest</code> parameter, for chaining.
318+
* @see #toString(JsonpSerializable)
319+
* @see #MAX_TO_STRING_LENGTH
320+
*/
271321
public static StringBuilder toString(JsonpSerializable value, StringBuilder dest) {
272322
return toString(value, ToStringMapper.INSTANCE, dest);
273323
}

java-client/src/test/java/co/elastic/clients/elasticsearch/json/JsonpUtilsTest.java

+23
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,29 @@ public String toString() {
8383
}
8484
}
8585

86+
@Test
87+
public void testLargeObjectToString() {
88+
// Build a large string
89+
StringBuilder sb = new StringBuilder();
90+
for (int i = 0; i < 1001; i++) {
91+
sb.append("0123456789");
92+
}
93+
94+
String text = sb.toString();
95+
assertEquals(10010, text.length());
96+
97+
Hit<String> hit = Hit.of(h -> h
98+
.source(text)
99+
.index("idx")
100+
.id("id1")
101+
);
102+
103+
String toString = hit.toString();
104+
105+
assertEquals(10003, toString.length());
106+
assertTrue(toString.endsWith("..."));
107+
}
108+
86109
@Test
87110
public void testSerializeDoubleOrNull() {
88111
// ---- Double values

0 commit comments

Comments
 (0)