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 google#1127.
  • Loading branch information
Capstan committed Jun 8, 2022
1 parent 15b9fa9 commit c7dbc55
Show file tree
Hide file tree
Showing 2 changed files with 85 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
66 changes: 66 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,36 @@ 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(3.723379f);
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.723379,"
+ "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 c7dbc55

Please sign in to comment.