Skip to content

Commit

Permalink
Add explicit support for floats in JsonWriter.
Browse files Browse the repository at this point in the history
This avoids floats being treated as doubles and having an unwarranted level of precision.

Fixes #1127.
  • Loading branch information
Capstan committed Jun 8, 2022
1 parent 15b9fa9 commit 62ab77e
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 0 deletions.
19 changes: 19 additions & 0 deletions gson/src/main/java/com/google/gson/stream/JsonWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,25 @@ public JsonWriter value(Boolean value) throws IOException {
return this;
}

/**
* Encodes {@code value}.
*
* @param value a finite value. May not be {@link Float#isNaN() NaNs} or {@link Float#isInfinite()
* infinities}.
* @return this writer.
* @throws IllegalArgumentException if the value is NaN or Infinity and this writer is not {@link
* #setLenient(boolean) lenient}.
*/
public JsonWriter value(float value) throws IOException {
writeDeferredName();
if (!lenient && (Float.isNaN(value) || Float.isInfinite(value))) {
throw new IllegalArgumentException("Numeric values must be finite, but was " + value);
}
beforeValue();
out.append(Float.toString(value));
return this;
}

/**
* Encodes {@code value}.
*
Expand Down
64 changes: 64 additions & 0 deletions gson/src/test/java/com/google/gson/stream/JsonWriterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,30 @@ public void testJsonValue() throws IOException {
assertEquals("{\"a\":{\"b\":true},\"c\":1}", stringWriter.toString());
}

public void testNonFiniteFloats() throws IOException {
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
jsonWriter.beginArray();
try {
jsonWriter.value(Float.NaN);
fail();
} catch (IllegalArgumentException expected) {
assertEquals("Numeric values must be finite, but was NaN", expected.getMessage());
}
try {
jsonWriter.value(Float.NEGATIVE_INFINITY);
fail();
} catch (IllegalArgumentException expected) {
assertEquals("Numeric values must be finite, but was -Infinity", expected.getMessage());
}
try {
jsonWriter.value(Float.POSITIVE_INFINITY);
fail();
} catch (IllegalArgumentException expected) {
assertEquals("Numeric values must be finite, but was Infinity", expected.getMessage());
}
}

public void testNonFiniteDoubles() throws IOException {
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
Expand Down Expand Up @@ -226,6 +250,18 @@ public void testNonFiniteNumbers() throws IOException {
}
}

public void testNonFiniteFloatsWhenLenient() throws IOException {
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
jsonWriter.setLenient(true);
jsonWriter.beginArray();
jsonWriter.value(Float.NaN);
jsonWriter.value(Float.NEGATIVE_INFINITY);
jsonWriter.value(Float.POSITIVE_INFINITY);
jsonWriter.endArray();
assertEquals("[NaN,-Infinity,Infinity]", stringWriter.toString());
}

public void testNonFiniteDoublesWhenLenient() throws IOException {
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
Expand All @@ -251,6 +287,34 @@ public void testNonFiniteNumbersWhenLenient() throws IOException {
assertEquals("[NaN,-Infinity,Infinity,Infinity]", stringWriter.toString());
}

public void testFloats() throws IOException {
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
jsonWriter.beginArray();
jsonWriter.value(-0.0f);
jsonWriter.value(1.0f);
jsonWriter.value(Float.MAX_VALUE);
jsonWriter.value(Float.MIN_VALUE);
jsonWriter.value(0.0f);
jsonWriter.value(-0.5f);
jsonWriter.value(2.2250739E-38f);
jsonWriter.value((float) Math.PI);
jsonWriter.value((float) Math.E);
jsonWriter.endArray();
jsonWriter.close();
assertEquals(
"[-0.0,"
+ "1.0,"
+ "3.4028235E38,"
+ "1.4E-45,"
+ "0.0,"
+ "-0.5,"
+ "2.2250739E-38,"
+ "3.1415927,"
+ "2.7182817]",
stringWriter.toString());
}

public void testDoubles() throws IOException {
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
Expand Down

0 comments on commit 62ab77e

Please sign in to comment.