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 f08a698240..355f8f763b 100644 --- a/gson/src/main/java/com/google/gson/stream/JsonWriter.java +++ b/gson/src/main/java/com/google/gson/stream/JsonWriter.java @@ -576,10 +576,10 @@ public JsonWriter value(Boolean value) throws IOException { */ @CanIgnoreReturnValue public JsonWriter value(float value) throws IOException { - writeDeferredName(); if (strictness != Strictness.LENIENT && (Float.isNaN(value) || Float.isInfinite(value))) { throw new IllegalArgumentException("Numeric values must be finite, but was " + value); } + writeDeferredName(); beforeValue(); out.append(Float.toString(value)); return this; @@ -596,10 +596,10 @@ public JsonWriter value(float value) throws IOException { */ @CanIgnoreReturnValue public JsonWriter value(double value) throws IOException { - writeDeferredName(); if (strictness != Strictness.LENIENT && (Double.isNaN(value) || Double.isInfinite(value))) { throw new IllegalArgumentException("Numeric values must be finite, but was " + value); } + writeDeferredName(); beforeValue(); out.append(Double.toString(value)); return this; @@ -635,7 +635,6 @@ public JsonWriter value(Number value) throws IOException { return nullValue(); } - writeDeferredName(); String string = value.toString(); Class numberClass = value.getClass(); @@ -653,6 +652,7 @@ public JsonWriter value(Number value) throws IOException { } } + writeDeferredName(); beforeValue(); out.append(string); return this; 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..ab926ba9dc 100644 --- a/gson/src/test/java/com/google/gson/stream/JsonWriterTest.java +++ b/gson/src/test/java/com/google/gson/stream/JsonWriterTest.java @@ -423,6 +423,51 @@ public void testNonFiniteNumbersWhenLenient() throws IOException { assertThat(stringWriter.toString()).isEqualTo("[NaN,-Infinity,Infinity,Infinity]"); } + /** + * Regression test for https://github.com/google/gson/issues/1736 + * + *

When a non-finite value is rejected, the deferred name should not have been written yet, so + * the writer state remains consistent. + */ + @Test + public void testNonFiniteValueDoesNotWriteDeferredName() throws IOException { + StringWriter stringWriter = new StringWriter(); + JsonWriter jsonWriter = new JsonWriter(stringWriter); + jsonWriter.setSerializeNulls(false); + jsonWriter.beginObject(); + + // value(float) with NaN should not write the name + jsonWriter.name("a"); + assertThrows(IllegalArgumentException.class, () -> jsonWriter.value(Float.NaN)); + jsonWriter.nullValue(); // should be suppressed since serializeNulls=false + + // value(double) with NaN should not write the name + jsonWriter.name("b"); + assertThrows(IllegalArgumentException.class, () -> jsonWriter.value(Double.NaN)); + jsonWriter.nullValue(); + + // value(double) with Infinity should not write the name + jsonWriter.name("c"); + assertThrows(IllegalArgumentException.class, () -> jsonWriter.value(Double.POSITIVE_INFINITY)); + jsonWriter.nullValue(); + + // value(Number) with NaN should not write the name + jsonWriter.name("d"); + assertThrows( + IllegalArgumentException.class, () -> jsonWriter.value(Double.valueOf(Double.NaN))); + jsonWriter.nullValue(); + + // value(Number) with invalid number string should not write the name + jsonWriter.name("e"); + assertThrows( + IllegalArgumentException.class, + () -> jsonWriter.value(new LazilyParsedNumber("not-a-num"))); + jsonWriter.nullValue(); + + jsonWriter.endObject(); + assertThat(stringWriter.toString()).isEqualTo("{}"); + } + @Test public void testFloats() throws IOException { StringWriter stringWriter = new StringWriter();