Skip to content

Commit

Permalink
Improve JsonWriter#value(Number) performance
Browse files Browse the repository at this point in the history
For JDK number types other than `Float` and `Double` there is no need to
check if the number string is NaN or Infinity.
  • Loading branch information
Marcono1234 committed Jun 15, 2024
1 parent 99cc4cb commit 6ac3044
Showing 1 changed file with 14 additions and 17 deletions.
31 changes: 14 additions & 17 deletions gson/src/main/java/com/google/gson/stream/JsonWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -638,15 +638,17 @@ public JsonWriter value(Number value) throws IOException {

writeDeferredName();
String string = value.toString();
if (string.equals("-Infinity") || string.equals("Infinity") || string.equals("NaN")) {
if (strictness != Strictness.LENIENT) {
throw new IllegalArgumentException("Numeric values must be finite, but was " + string);
}
} else {
Class<? extends Number> numberClass = value.getClass();
Class<? extends Number> numberClass = value.getClass();

if (!alwaysCreatesValidJsonNumber(numberClass)) {
// Validate that string is valid before writing it directly to JSON output
if (!isTrustedNumberType(numberClass)
&& !VALID_JSON_NUMBER_PATTERN.matcher(string).matches()) {
if (string.equals("-Infinity") || string.equals("Infinity") || string.equals("NaN")) {
if (strictness != Strictness.LENIENT) {
throw new IllegalArgumentException("Numeric values must be finite, but was " + string);
}
} else if (!(numberClass == Float.class
|| numberClass == Double.class
|| VALID_JSON_NUMBER_PATTERN.matcher(string).matches())) {
throw new IllegalArgumentException(
"String created by " + numberClass + " is not a valid JSON number: " + string);
}
Expand Down Expand Up @@ -725,17 +727,12 @@ public void close() throws IOException {
stackSize = 0;
}

/**
* Returns whether the {@code toString()} of {@code c} can be trusted to return a valid JSON
* number.
*/
private static boolean isTrustedNumberType(Class<? extends Number> c) {
// Note: Don't consider LazilyParsedNumber trusted because it could contain
// an arbitrary malformed string
/** Returns whether the {@code toString()} of {@code c} will always return a valid JSON number. */
private static boolean alwaysCreatesValidJsonNumber(Class<? extends Number> c) {
// Does not include Float or Double because their value can be NaN or Infinity
// Does not include LazilyParsedNumber because it could contain a malformed string
return c == Integer.class
|| c == Long.class
|| c == Double.class
|| c == Float.class
|| c == Byte.class
|| c == Short.class
|| c == BigDecimal.class
Expand Down

0 comments on commit 6ac3044

Please sign in to comment.