diff --git a/gson/src/main/java/com/google/gson/stream/JsonWriter.java b/gson/src/main/java/com/google/gson/stream/JsonWriter.java index 8bf3d8123f..70b0157b24 100644 --- a/gson/src/main/java/com/google/gson/stream/JsonWriter.java +++ b/gson/src/main/java/com/google/gson/stream/JsonWriter.java @@ -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 numberClass = value.getClass(); + Class 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); @@ -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 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 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