Add explicit support for floats in JsonWriter. (#2130)

This avoids floats being treated as doubles and having an unwarranted level of precision.

Fixes #1127.
This commit is contained in:
Nathan Herring 2022-06-08 15:04:42 -07:00 committed by GitHub
parent 15b9fa9c31
commit 96ab171eb4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 85 additions and 0 deletions

View File

@ -490,6 +490,25 @@ public class JsonWriter implements Closeable, Flushable {
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}.
*

View File

@ -172,6 +172,30 @@ public final class JsonWriterTest extends TestCase {
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);
@ -226,6 +250,18 @@ public final class JsonWriterTest extends TestCase {
}
}
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);
@ -251,6 +287,36 @@ public final class JsonWriterTest extends TestCase {
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);