From 4732c7ff40441ac16c8e69e38be58e20898ead82 Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Mon, 16 Dec 2024 00:31:56 +0100 Subject: [PATCH 1/4] Add better support for multiple top-level values --- .../com/google/gson/stream/JsonReader.java | 46 ++++++++-- .../com/google/gson/stream/JsonWriter.java | 54 ++++++++++-- .../test/java/com/google/gson/GsonTest.java | 6 +- .../internal/bind/JsonTreeReaderTest.java | 2 + .../internal/bind/JsonTreeWriterTest.java | 2 + .../google/gson/stream/JsonReaderTest.java | 83 ++++++++++++++++++- .../google/gson/stream/JsonWriterTest.java | 80 +++++++++++++++++- 7 files changed, 255 insertions(+), 18 deletions(-) diff --git a/gson/src/main/java/com/google/gson/stream/JsonReader.java b/gson/src/main/java/com/google/gson/stream/JsonReader.java index 30876109a5..927c57662a 100644 --- a/gson/src/main/java/com/google/gson/stream/JsonReader.java +++ b/gson/src/main/java/com/google/gson/stream/JsonReader.java @@ -70,8 +70,9 @@ * The behavior of this reader can be customized with the following methods: * * * * The default configuration of {@code JsonReader} instances used internally by the {@link Gson} @@ -257,6 +258,8 @@ public class JsonReader implements Closeable { static final int DEFAULT_NESTING_LIMIT = 255; private int nestingLimit = DEFAULT_NESTING_LIMIT; + private boolean multiTopLevelValuesEnabled = false; + static final int BUFFER_SIZE = 1024; /** @@ -380,7 +383,8 @@ public final boolean isLenient() { *
  • Streams that start with the non-execute prefix, * {@code ")]}'\n"} *
  • Streams that include multiple top-level values. With legacy strict or strict - * parsing, each stream must contain exactly one top-level value. + * parsing, each stream must contain exactly one top-level value. Can be enabled + * independently using {@link #setMultiTopLevelValuesAllowed(boolean)}. *
  • Numbers may be {@link Double#isNaN() NaNs} or {@link Double#isInfinite() * infinities} represented by {@code NaN} and {@code (-)Infinity} respectively. *
  • End of line comments starting with {@code //} or {@code #} and ending with a @@ -402,8 +406,8 @@ public final boolean isLenient() { * @since 2.11.0 */ public final void setStrictness(Strictness strictness) { - Objects.requireNonNull(strictness); - this.strictness = strictness; + this.strictness = Objects.requireNonNull(strictness); + setMultiTopLevelValuesAllowed(strictness == Strictness.LENIENT); } /** @@ -416,6 +420,31 @@ public final Strictness getStrictness() { return strictness; } + /** + * Sets whether multiple top-level values are allowed. Only whitespace is supported as separator + * between top-level values. Values may also be concatenated without any whitespace in between, + * but for some values this causes ambiguities, for example for JSON numbers as top-level values. + * + *

    This setting overwrites and is overwritten by whether {@link #setStrictness(Strictness)} + * enabled support for multiple top-level values. + * + * @see #isMultiTopLevelValuesAllowed() + * @since $next-version$ + */ + public final void setMultiTopLevelValuesAllowed(boolean enabled) { + this.multiTopLevelValuesEnabled = enabled; + } + + /** + * Returns whether multiple top-level values are allowed. + * + * @see #setMultiTopLevelValuesAllowed(boolean) + * @since $next-version$ + */ + public final boolean isMultiTopLevelValuesAllowed() { + return multiTopLevelValuesEnabled; + } + /** * Sets the nesting limit of this reader. * @@ -661,10 +690,13 @@ int doPeek() throws IOException { int c = nextNonWhitespace(false); if (c == -1) { return peeked = PEEKED_EOF; - } else { - checkLenient(); - pos--; + } else if (!multiTopLevelValuesEnabled) { + throw new MalformedJsonException( + "Multiple top-level values support has not been enabled, use" + + " `JsonReader.setMultiTopLevelValuesAllowed(true)`," + + locationString()); } + pos--; } else if (peekStack == JsonScope.CLOSED) { throw new IllegalStateException("JsonReader is closed"); } diff --git a/gson/src/main/java/com/google/gson/stream/JsonWriter.java b/gson/src/main/java/com/google/gson/stream/JsonWriter.java index 70b0157b24..10f761b70f 100644 --- a/gson/src/main/java/com/google/gson/stream/JsonWriter.java +++ b/gson/src/main/java/com/google/gson/stream/JsonWriter.java @@ -72,6 +72,7 @@ * output *

  • {@link #setStrictness(Strictness)}, the default is {@link Strictness#LEGACY_STRICT} *
  • {@link #setSerializeNulls(boolean)}, by default {@code null} is serialized + *
  • {@link #setTopLevelSeparator(String)}, by default {@code null} (= disabled) * * * The default configuration of {@code JsonWriter} instances used internally by the {@link Gson} @@ -218,6 +219,11 @@ public class JsonWriter implements Closeable, Flushable { private Strictness strictness = Strictness.LEGACY_STRICT; + /** + * Separator between top-level values; {@code null} if multiple top-level values are not allowed + */ + private String topLevelSeparator = null; + private boolean htmlSafe; private String deferredName; @@ -334,9 +340,13 @@ public boolean isLenient() { *
    The behavior of these is currently identical. In these strictness modes, the writer only * writes JSON in accordance with RFC 8259. *
    {@link Strictness#LENIENT} - *
    This mode relaxes the behavior of the writer to allow the writing of {@link - * Double#isNaN() NaNs} and {@link Double#isInfinite() infinities}. It also allows writing - * multiple top level values. + *
    In lenient mode, the following departures from RFC 8259 are permitted: + *
      + *
    • Writing of {@link Double#isNaN() NaNs} and {@link Double#isInfinite() infinities}. + *
    • Writing multiple top level values. The values are concatenated without any + * separating whitespace. Can be enabled independently and can be further customized + * using {@link #setTopLevelSeparator(String)}. + *
    * * * @param strictness the new strictness of this writer. May not be {@code null}. @@ -345,6 +355,7 @@ public boolean isLenient() { */ public final void setStrictness(Strictness strictness) { this.strictness = Objects.requireNonNull(strictness); + setTopLevelSeparator(strictness == Strictness.LENIENT ? "" : null); } /** @@ -357,6 +368,33 @@ public final Strictness getStrictness() { return strictness; } + /** + * Sets the separator to use between multiple top-level values. When writing multiple top-level + * values the separator is written between the values, this can for example be useful for formats + * such as JSON Lines.
    + * Using {@code null} disables support for multiple top-level values (the default). + * + *

    This setting overwrites and is overwritten by whether {@link #setStrictness(Strictness)} + * enabled support for multiple top-level values. + * + * @param separator separator between top-level values, or {@code null} to disable. + * @see #getTopLevelSeparator() + * @since $next-version$ + */ + public final void setTopLevelSeparator(String separator) { + this.topLevelSeparator = separator; + } + + /** + * Returns the top-level separator, or {@code null} if disabled. + * + * @see #setTopLevelSeparator(String) + * @since $next-version$ + */ + public final String getTopLevelSeparator() { + return topLevelSeparator; + } + /** * Configures this writer to emit JSON that's safe for direct inclusion in HTML and XML documents. * This escapes the HTML characters {@code <}, {@code >}, {@code &}, {@code =} and {@code '} @@ -807,10 +845,14 @@ private void beforeName() throws IOException { private void beforeValue() throws IOException { switch (peek()) { case NONEMPTY_DOCUMENT: - if (strictness != Strictness.LENIENT) { - throw new IllegalStateException("JSON must have only one top-level value."); + if (topLevelSeparator == null) { + throw new IllegalStateException( + "Multiple top-level values support has not been enabled, use" + + " `JsonWriter.setTopLevelSeparator(String)`"); } - // fall-through + out.append(topLevelSeparator); + break; + case EMPTY_DOCUMENT: // first in document replaceTop(NONEMPTY_DOCUMENT); break; diff --git a/gson/src/test/java/com/google/gson/GsonTest.java b/gson/src/test/java/com/google/gson/GsonTest.java index 45cd1d4479..be005424f7 100644 --- a/gson/src/test/java/com/google/gson/GsonTest.java +++ b/gson/src/test/java/com/google/gson/GsonTest.java @@ -411,7 +411,11 @@ public void testNewJsonWriter_Default() throws IOException { // Additional top-level value IllegalStateException e = assertThrows(IllegalStateException.class, () -> jsonWriter.value(1)); - assertThat(e).hasMessageThat().isEqualTo("JSON must have only one top-level value."); + assertThat(e) + .hasMessageThat() + .isEqualTo( + "Multiple top-level values support has not been enabled, use" + + " `JsonWriter.setTopLevelSeparator(String)`"); jsonWriter.close(); assertThat(writer.toString()).isEqualTo("{\"\\u003ctest2\":true}"); diff --git a/gson/src/test/java/com/google/gson/internal/bind/JsonTreeReaderTest.java b/gson/src/test/java/com/google/gson/internal/bind/JsonTreeReaderTest.java index 42d4649683..4d013da82b 100644 --- a/gson/src/test/java/com/google/gson/internal/bind/JsonTreeReaderTest.java +++ b/gson/src/test/java/com/google/gson/internal/bind/JsonTreeReaderTest.java @@ -195,6 +195,8 @@ public void testOverrides() { "isLenient()", "setStrictness(com.google.gson.Strictness)", "getStrictness()", + "setMultiTopLevelValuesAllowed(boolean)", + "isMultiTopLevelValuesAllowed()", "setNestingLimit(int)", "getNestingLimit()"); MoreAsserts.assertOverridesMethods(JsonReader.class, JsonTreeReader.class, ignoredMethods); diff --git a/gson/src/test/java/com/google/gson/internal/bind/JsonTreeWriterTest.java b/gson/src/test/java/com/google/gson/internal/bind/JsonTreeWriterTest.java index 97dc2e56c0..8d3006e8e0 100644 --- a/gson/src/test/java/com/google/gson/internal/bind/JsonTreeWriterTest.java +++ b/gson/src/test/java/com/google/gson/internal/bind/JsonTreeWriterTest.java @@ -272,6 +272,8 @@ public void testOverrides() { "isLenient()", "setStrictness(com.google.gson.Strictness)", "getStrictness()", + "setTopLevelSeparator(java.lang.String)", + "getTopLevelSeparator()", "setIndent(java.lang.String)", "setHtmlSafe(boolean)", "isHtmlSafe()", diff --git a/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java b/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java index f8a33be0df..8d055f1f03 100644 --- a/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java +++ b/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java @@ -1460,7 +1460,17 @@ public void testStrictMultipleTopLevelValues() throws IOException { reader.beginArray(); reader.endArray(); var e = assertThrows(MalformedJsonException.class, () -> reader.peek()); - assertStrictError(e, "line 1 column 5 path $"); + assertThat(e) + .hasMessageThat() + .isEqualTo( + "Multiple top-level values support has not been enabled, use" + + " `JsonReader.setMultiTopLevelValuesAllowed(true)`, at line 1 column 5 path $"); + + // But trailing whitespace is allowed + JsonReader reader2 = new JsonReader(reader("[] \n \t \r ")); + reader2.beginArray(); + reader2.endArray(); + assertThat(reader2.peek()).isEqualTo(JsonToken.END_DOCUMENT); } @Test @@ -1481,7 +1491,76 @@ public void testStrictMultipleTopLevelValuesWithSkipValue() throws IOException { reader.beginArray(); reader.endArray(); var e = assertThrows(MalformedJsonException.class, () -> reader.skipValue()); - assertStrictError(e, "line 1 column 5 path $"); + assertThat(e) + .hasMessageThat() + .isEqualTo( + "Multiple top-level values support has not been enabled, use" + + " `JsonReader.setMultiTopLevelValuesAllowed(true)`, at line 1 column 5 path $"); + } + + @Test + public void testMultipleTopLevelValuesStrictness() { + JsonReader reader = new JsonReader(reader("[]")); + assertThat(reader.isMultiTopLevelValuesAllowed()).isFalse(); + + reader.setStrictness(Strictness.STRICT); + assertThat(reader.isMultiTopLevelValuesAllowed()).isFalse(); + + reader.setStrictness(Strictness.LEGACY_STRICT); + assertThat(reader.isMultiTopLevelValuesAllowed()).isFalse(); + + reader.setStrictness(Strictness.LENIENT); + assertThat(reader.isMultiTopLevelValuesAllowed()).isTrue(); + + reader.setStrictness(Strictness.STRICT); + assertThat(reader.isMultiTopLevelValuesAllowed()).isFalse(); + // Verify that it can be enabled independently of Strictness + reader.setMultiTopLevelValuesAllowed(true); + assertThat(reader.getStrictness()).isEqualTo(Strictness.STRICT); + assertThat(reader.isMultiTopLevelValuesAllowed()).isTrue(); + } + + /** + * Tests multiple top-level values, enabled with {@link + * JsonReader#setMultiTopLevelValuesAllowed(boolean)}. + */ + @Test + public void testMultipleTopLevelValuesEnabled() throws IOException { + JsonReader reader = new JsonReader(reader("[]{}")); + reader.setStrictness(Strictness.STRICT); + reader.setMultiTopLevelValuesAllowed(true); + + reader.beginArray(); + reader.endArray(); + reader.beginObject(); + reader.endObject(); + assertThat(reader.peek()).isEqualTo(JsonToken.END_DOCUMENT); + + reader = new JsonReader(reader("true\n \n1")); + reader.setStrictness(Strictness.STRICT); + reader.setMultiTopLevelValuesAllowed(true); + + assertThat(reader.nextBoolean()).isTrue(); + assertThat(reader.nextInt()).isEqualTo(1); + assertThat(reader.peek()).isEqualTo(JsonToken.END_DOCUMENT); + } + + @Test + public void testMultipleTopLevelValuesDisabled() throws IOException { + JsonReader reader = new JsonReader(reader("[]{}")); + // Normally lenient mode allows multiple top-level values + reader.setStrictness(Strictness.LENIENT); + reader.setMultiTopLevelValuesAllowed(false); + + reader.beginArray(); + reader.endArray(); + + var e = assertThrows(MalformedJsonException.class, () -> reader.beginObject()); + assertThat(e) + .hasMessageThat() + .isEqualTo( + "Multiple top-level values support has not been enabled, use" + + " `JsonReader.setMultiTopLevelValuesAllowed(true)`, at line 1 column 4 path $"); } @Test diff --git a/gson/src/test/java/com/google/gson/stream/JsonWriterTest.java b/gson/src/test/java/com/google/gson/stream/JsonWriterTest.java index fd171e880f..2db07386d3 100644 --- a/gson/src/test/java/com/google/gson/stream/JsonWriterTest.java +++ b/gson/src/test/java/com/google/gson/stream/JsonWriterTest.java @@ -181,7 +181,11 @@ public void testMultipleTopLevelValues() throws IOException { IllegalStateException expected = assertThrows(IllegalStateException.class, jsonWriter::beginArray); - assertThat(expected).hasMessageThat().isEqualTo("JSON must have only one top-level value."); + assertThat(expected) + .hasMessageThat() + .isEqualTo( + "Multiple top-level values support has not been enabled, use" + + " `JsonWriter.setTopLevelSeparator(String)`"); } @Test @@ -193,7 +197,11 @@ public void testMultipleTopLevelValuesStrict() throws IOException { IllegalStateException expected = assertThrows(IllegalStateException.class, jsonWriter::beginArray); - assertThat(expected).hasMessageThat().isEqualTo("JSON must have only one top-level value."); + assertThat(expected) + .hasMessageThat() + .isEqualTo( + "Multiple top-level values support has not been enabled, use" + + " `JsonWriter.setTopLevelSeparator(String)`"); } @Test @@ -209,6 +217,74 @@ public void testMultipleTopLevelValuesLenient() throws IOException { assertThat(stringWriter.toString()).isEqualTo("[][]"); } + @Test + public void testMultipleTopLevelValuesStrictness() { + JsonWriter writer = new JsonWriter(new StringWriter()); + assertThat(writer.getTopLevelSeparator()).isNull(); + + writer.setStrictness(Strictness.STRICT); + assertThat(writer.getTopLevelSeparator()).isNull(); + + writer.setStrictness(Strictness.LEGACY_STRICT); + assertThat(writer.getTopLevelSeparator()).isNull(); + + writer.setStrictness(Strictness.LENIENT); + assertThat(writer.getTopLevelSeparator()).isEqualTo(""); + + writer.setStrictness(Strictness.STRICT); + assertThat(writer.getTopLevelSeparator()).isNull(); + // Verify that it can be enabled independently of Strictness + writer.setTopLevelSeparator("\n"); + assertThat(writer.getStrictness()).isEqualTo(Strictness.STRICT); + assertThat(writer.getTopLevelSeparator()).isEqualTo("\n"); + } + + /** + * Tests multiple top-level values, enabled with {@link JsonWriter#setTopLevelSeparator(String)}. + */ + @Test + public void testMultipleTopLevelValuesEnabled() throws IOException { + StringWriter stringWriter = new StringWriter(); + JsonWriter writer = new JsonWriter(stringWriter); + writer.setStrictness(Strictness.STRICT); + writer.setTopLevelSeparator(""); + + writer.beginArray(); + writer.endArray(); + writer.beginObject(); + writer.endObject(); + writer.close(); + assertThat(stringWriter.toString()).isEqualTo("[]{}"); + + stringWriter = new StringWriter(); + writer = new JsonWriter(stringWriter); + writer.setStrictness(Strictness.STRICT); + writer.setTopLevelSeparator(" \n "); + + writer.value(1); + writer.value(2); + writer.close(); + assertThat(stringWriter.toString()).isEqualTo("1 \n 2"); + } + + @Test + public void testMultipleTopLevelValuesDisabled() throws IOException { + StringWriter stringWriter = new StringWriter(); + JsonWriter writer = new JsonWriter(stringWriter); + // Normally lenient mode allows multiple top-level values + writer.setStrictness(Strictness.LENIENT); + writer.setTopLevelSeparator(null); + + writer.value(1); + + var e = assertThrows(IllegalStateException.class, () -> writer.value(2)); + assertThat(e) + .hasMessageThat() + .isEqualTo( + "Multiple top-level values support has not been enabled, use" + + " `JsonWriter.setTopLevelSeparator(String)`"); + } + @Test public void testBadNestingObject() throws IOException { StringWriter stringWriter = new StringWriter(); From c8c9814bbc73a787c2c30a73f6bfa747a5fa6c8d Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Fri, 20 Feb 2026 18:27:18 +0100 Subject: [PATCH 2/4] Extend tests --- .../src/test/java/com/google/gson/stream/JsonReaderTest.java | 5 +++++ .../src/test/java/com/google/gson/stream/JsonWriterTest.java | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java b/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java index 7f122c5955..0f30a99dd4 100644 --- a/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java +++ b/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java @@ -1550,7 +1550,12 @@ public void testMultipleTopLevelValuesDisabled() throws IOException { JsonReader reader = new JsonReader(reader("[]{}")); // Normally lenient mode allows multiple top-level values reader.setStrictness(Strictness.LENIENT); + assertThat(reader.isMultiTopLevelValuesAllowed()).isTrue(); + + // But explicitly disable it reader.setMultiTopLevelValuesAllowed(false); + assertThat(reader.getStrictness()).isEqualTo(Strictness.LENIENT); + assertThat(reader.isMultiTopLevelValuesAllowed()).isFalse(); reader.beginArray(); reader.endArray(); diff --git a/gson/src/test/java/com/google/gson/stream/JsonWriterTest.java b/gson/src/test/java/com/google/gson/stream/JsonWriterTest.java index 2db07386d3..77874397eb 100644 --- a/gson/src/test/java/com/google/gson/stream/JsonWriterTest.java +++ b/gson/src/test/java/com/google/gson/stream/JsonWriterTest.java @@ -273,7 +273,12 @@ public void testMultipleTopLevelValuesDisabled() throws IOException { JsonWriter writer = new JsonWriter(stringWriter); // Normally lenient mode allows multiple top-level values writer.setStrictness(Strictness.LENIENT); + assertThat(writer.getTopLevelSeparator()).isEqualTo(""); + + // But explicitly disable it writer.setTopLevelSeparator(null); + assertThat(writer.getStrictness()).isEqualTo(Strictness.LENIENT); + assertThat(writer.getTopLevelSeparator()).isNull(); writer.value(1); From 7960590824d19abcc64f819dd369a79ea1847ae6 Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Fri, 20 Feb 2026 18:34:54 +0100 Subject: [PATCH 3/4] Rename JsonReader methods to suggested names --- .../com/google/gson/stream/JsonReader.java | 26 +++++++-------- .../internal/bind/JsonTreeReaderTest.java | 4 +-- .../google/gson/stream/JsonReaderTest.java | 32 +++++++++---------- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/gson/src/main/java/com/google/gson/stream/JsonReader.java b/gson/src/main/java/com/google/gson/stream/JsonReader.java index 619a0cf048..322233bbf2 100644 --- a/gson/src/main/java/com/google/gson/stream/JsonReader.java +++ b/gson/src/main/java/com/google/gson/stream/JsonReader.java @@ -67,7 +67,7 @@ * The behavior of this reader can be customized with the following methods: * *

      - *
    • {@link #setMultiTopLevelValuesAllowed(boolean)}, the default is {@code false} + *
    • {@link #setAllowingMultipleValues(boolean)}, the default is {@code false} *
    • {@link #setNestingLimit(int)}, the default is {@value #DEFAULT_NESTING_LIMIT} *
    • {@link #setStrictness(Strictness)}, the default is {@link Strictness#LEGACY_STRICT} *
    • {@link #setNestingLimit(int)}, the default is {@value #DEFAULT_NESTING_LIMIT} @@ -257,7 +257,7 @@ public class JsonReader implements Closeable { static final int DEFAULT_NESTING_LIMIT = 255; private int nestingLimit = DEFAULT_NESTING_LIMIT; - private boolean multiTopLevelValuesEnabled = false; + private boolean multiTopLevelValuesAllowed = false; static final int BUFFER_SIZE = 1024; @@ -383,7 +383,7 @@ public final boolean isLenient() { * {@code ")]}'\n"} *
    • Streams that include multiple top-level values. With legacy strict or strict * parsing, each stream must contain exactly one top-level value. Can be enabled - * independently using {@link #setMultiTopLevelValuesAllowed(boolean)}. + * independently using {@link #setAllowingMultipleValues(boolean)}. *
    • Numbers may be {@link Double#isNaN() NaNs} or {@link Double#isInfinite() * infinities} represented by {@code NaN} and {@code (-)Infinity} respectively. *
    • End of line comments starting with {@code //} or {@code #} and ending with a @@ -406,7 +406,7 @@ public final boolean isLenient() { */ public final void setStrictness(Strictness strictness) { this.strictness = Objects.requireNonNull(strictness); - setMultiTopLevelValuesAllowed(strictness == Strictness.LENIENT); + setAllowingMultipleValues(strictness == Strictness.LENIENT); } /** @@ -425,23 +425,23 @@ public final Strictness getStrictness() { * but for some values this causes ambiguities, for example for JSON numbers as top-level values. * *

      This setting overwrites and is overwritten by whether {@link #setStrictness(Strictness)} - * enabled support for multiple top-level values. + * allowed support for multiple top-level values. * - * @see #isMultiTopLevelValuesAllowed() + * @see #isAllowingMultipleValues() * @since $next-version$ */ - public final void setMultiTopLevelValuesAllowed(boolean enabled) { - this.multiTopLevelValuesEnabled = enabled; + public final void setAllowingMultipleValues(boolean allowed) { + this.multiTopLevelValuesAllowed = allowed; } /** * Returns whether multiple top-level values are allowed. * - * @see #setMultiTopLevelValuesAllowed(boolean) + * @see #setAllowingMultipleValues(boolean) * @since $next-version$ */ - public final boolean isMultiTopLevelValuesAllowed() { - return multiTopLevelValuesEnabled; + public final boolean isAllowingMultipleValues() { + return multiTopLevelValuesAllowed; } /** @@ -696,10 +696,10 @@ int doPeek() throws IOException { if (c == -1) { peeked = PEEKED_EOF; return peeked; - } else if (!multiTopLevelValuesEnabled) { + } else if (!multiTopLevelValuesAllowed) { throw new MalformedJsonException( "Multiple top-level values support has not been enabled, use" - + " `JsonReader.setMultiTopLevelValuesAllowed(true)`," + + " `JsonReader.setAllowingMultipleValues(true)`," + locationString()); } pos--; diff --git a/gson/src/test/java/com/google/gson/internal/bind/JsonTreeReaderTest.java b/gson/src/test/java/com/google/gson/internal/bind/JsonTreeReaderTest.java index 4d013da82b..24beb320a1 100644 --- a/gson/src/test/java/com/google/gson/internal/bind/JsonTreeReaderTest.java +++ b/gson/src/test/java/com/google/gson/internal/bind/JsonTreeReaderTest.java @@ -195,8 +195,8 @@ public void testOverrides() { "isLenient()", "setStrictness(com.google.gson.Strictness)", "getStrictness()", - "setMultiTopLevelValuesAllowed(boolean)", - "isMultiTopLevelValuesAllowed()", + "setAllowingMultipleValues(boolean)", + "isAllowingMultipleValues()", "setNestingLimit(int)", "getNestingLimit()"); MoreAsserts.assertOverridesMethods(JsonReader.class, JsonTreeReader.class, ignoredMethods); diff --git a/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java b/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java index 0f30a99dd4..7ae2b0eb98 100644 --- a/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java +++ b/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java @@ -1464,7 +1464,7 @@ public void testStrictMultipleTopLevelValues() throws IOException { .hasMessageThat() .isEqualTo( "Multiple top-level values support has not been enabled, use" - + " `JsonReader.setMultiTopLevelValuesAllowed(true)`, at line 1 column 5 path $"); + + " `JsonReader.setAllowingMultipleValues(true)`, at line 1 column 5 path $"); // But trailing whitespace is allowed JsonReader reader2 = new JsonReader(reader("[] \n \t \r ")); @@ -1495,40 +1495,40 @@ public void testStrictMultipleTopLevelValuesWithSkipValue() throws IOException { .hasMessageThat() .isEqualTo( "Multiple top-level values support has not been enabled, use" - + " `JsonReader.setMultiTopLevelValuesAllowed(true)`, at line 1 column 5 path $"); + + " `JsonReader.setAllowingMultipleValues(true)`, at line 1 column 5 path $"); } @Test public void testMultipleTopLevelValuesStrictness() { JsonReader reader = new JsonReader(reader("[]")); - assertThat(reader.isMultiTopLevelValuesAllowed()).isFalse(); + assertThat(reader.isAllowingMultipleValues()).isFalse(); reader.setStrictness(Strictness.STRICT); - assertThat(reader.isMultiTopLevelValuesAllowed()).isFalse(); + assertThat(reader.isAllowingMultipleValues()).isFalse(); reader.setStrictness(Strictness.LEGACY_STRICT); - assertThat(reader.isMultiTopLevelValuesAllowed()).isFalse(); + assertThat(reader.isAllowingMultipleValues()).isFalse(); reader.setStrictness(Strictness.LENIENT); - assertThat(reader.isMultiTopLevelValuesAllowed()).isTrue(); + assertThat(reader.isAllowingMultipleValues()).isTrue(); reader.setStrictness(Strictness.STRICT); - assertThat(reader.isMultiTopLevelValuesAllowed()).isFalse(); + assertThat(reader.isAllowingMultipleValues()).isFalse(); // Verify that it can be enabled independently of Strictness - reader.setMultiTopLevelValuesAllowed(true); + reader.setAllowingMultipleValues(true); assertThat(reader.getStrictness()).isEqualTo(Strictness.STRICT); - assertThat(reader.isMultiTopLevelValuesAllowed()).isTrue(); + assertThat(reader.isAllowingMultipleValues()).isTrue(); } /** * Tests multiple top-level values, enabled with {@link - * JsonReader#setMultiTopLevelValuesAllowed(boolean)}. + * JsonReader#setAllowingMultipleValues(boolean)}. */ @Test public void testMultipleTopLevelValuesEnabled() throws IOException { JsonReader reader = new JsonReader(reader("[]{}")); reader.setStrictness(Strictness.STRICT); - reader.setMultiTopLevelValuesAllowed(true); + reader.setAllowingMultipleValues(true); reader.beginArray(); reader.endArray(); @@ -1538,7 +1538,7 @@ public void testMultipleTopLevelValuesEnabled() throws IOException { reader = new JsonReader(reader("true\n \n1")); reader.setStrictness(Strictness.STRICT); - reader.setMultiTopLevelValuesAllowed(true); + reader.setAllowingMultipleValues(true); assertThat(reader.nextBoolean()).isTrue(); assertThat(reader.nextInt()).isEqualTo(1); @@ -1550,12 +1550,12 @@ public void testMultipleTopLevelValuesDisabled() throws IOException { JsonReader reader = new JsonReader(reader("[]{}")); // Normally lenient mode allows multiple top-level values reader.setStrictness(Strictness.LENIENT); - assertThat(reader.isMultiTopLevelValuesAllowed()).isTrue(); + assertThat(reader.isAllowingMultipleValues()).isTrue(); // But explicitly disable it - reader.setMultiTopLevelValuesAllowed(false); + reader.setAllowingMultipleValues(false); assertThat(reader.getStrictness()).isEqualTo(Strictness.LENIENT); - assertThat(reader.isMultiTopLevelValuesAllowed()).isFalse(); + assertThat(reader.isAllowingMultipleValues()).isFalse(); reader.beginArray(); reader.endArray(); @@ -1565,7 +1565,7 @@ public void testMultipleTopLevelValuesDisabled() throws IOException { .hasMessageThat() .isEqualTo( "Multiple top-level values support has not been enabled, use" - + " `JsonReader.setMultiTopLevelValuesAllowed(true)`, at line 1 column 4 path $"); + + " `JsonReader.setAllowingMultipleValues(true)`, at line 1 column 4 path $"); } @Test From acb3990d6261e2dd0c23321a6aa1ef37fb519bde Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Fri, 20 Feb 2026 18:54:31 +0100 Subject: [PATCH 4/4] Sort methods alphabetically & fix duplicate line from merge --- gson/src/main/java/com/google/gson/stream/JsonReader.java | 1 - gson/src/main/java/com/google/gson/stream/JsonWriter.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/gson/src/main/java/com/google/gson/stream/JsonReader.java b/gson/src/main/java/com/google/gson/stream/JsonReader.java index 322233bbf2..ca5024d9cf 100644 --- a/gson/src/main/java/com/google/gson/stream/JsonReader.java +++ b/gson/src/main/java/com/google/gson/stream/JsonReader.java @@ -70,7 +70,6 @@ *

    • {@link #setAllowingMultipleValues(boolean)}, the default is {@code false} *
    • {@link #setNestingLimit(int)}, the default is {@value #DEFAULT_NESTING_LIMIT} *
    • {@link #setStrictness(Strictness)}, the default is {@link Strictness#LEGACY_STRICT} - *
    • {@link #setNestingLimit(int)}, the default is {@value #DEFAULT_NESTING_LIMIT} *
    * * The default configuration of {@code JsonReader} instances used internally by the {@link diff --git a/gson/src/main/java/com/google/gson/stream/JsonWriter.java b/gson/src/main/java/com/google/gson/stream/JsonWriter.java index 22a5538726..659ce56672 100644 --- a/gson/src/main/java/com/google/gson/stream/JsonWriter.java +++ b/gson/src/main/java/com/google/gson/stream/JsonWriter.java @@ -68,8 +68,8 @@ * FormattingStyle#COMPACT} *
  • {@link #setHtmlSafe(boolean)}, by default HTML characters are not escaped in the JSON * output - *
  • {@link #setStrictness(Strictness)}, the default is {@link Strictness#LEGACY_STRICT} *
  • {@link #setSerializeNulls(boolean)}, by default {@code null} is serialized + *
  • {@link #setStrictness(Strictness)}, the default is {@link Strictness#LEGACY_STRICT} *
  • {@link #setTopLevelSeparator(String)}, by default {@code null} (= disabled) * *