Skip to content

Commit

Permalink
Improve JsonWriter#value(Number) performance (#2702)
Browse files Browse the repository at this point in the history
* Improve `JsonWriter#value(Number)` performance

For JDK number types other than `Float` and `Double` there is no need to
check if the number string is NaN or Infinity.

* Refactor boolean expression
  • Loading branch information
Marcono1234 authored Jun 18, 2024
1 parent 99cc4cb commit d4d6744
Showing 1 changed file with 13 additions and 16 deletions.
29 changes: 13 additions & 16 deletions gson/src/main/java/com/google/gson/stream/JsonWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -638,14 +638,16 @@ 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)
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 d4d6744

Please sign in to comment.