Skip to content

Commit 454a491

Browse files
authored
Improved Long-Double Number Policy (#2674)
* Improved Long-Double Number Policy The Parsing of a Double value was always executing a `Long.parseLong(value)`, which generated a `NumberFormatException`. Identifying that a Number is a Double or a Long can be easily achieve (in a naive way) looking for the decimal separator. This simple change avoids the extra `NumberFormatException` A simple JUnit test, parsing a `Long` or a `Double` 10K times shows the next values: * Double (old parsing): ~42 ms * Double (new parsing): ~6 ms * Long (old parsing): ~7 ms * Long (new parsing): ~7 ms As we can see, the parsing for `Long` values stays the same (±1ms), while the parsing for `Double` is dramatically improved. Reducing the number of exceptions also has a positive side effect in memory consumption. * Replace `contains(".")` by `indexOf('.') >= 0` The usage of `indexOf(char)` is slightly faster * Rename exception variables
1 parent 570d911 commit 454a491

File tree

1 file changed

+20
-12
lines changed

1 file changed

+20
-12
lines changed

gson/src/main/java/com/google/gson/ToNumberPolicy.java

+20-12
Original file line numberDiff line numberDiff line change
@@ -68,22 +68,30 @@ public Number readNumber(JsonReader in) throws IOException {
6868
@Override
6969
public Number readNumber(JsonReader in) throws IOException, JsonParseException {
7070
String value = in.nextString();
71-
try {
72-
return Long.parseLong(value);
73-
} catch (NumberFormatException longE) {
71+
if (value.indexOf('.') >= 0) {
72+
return parseAsDouble(value, in);
73+
} else {
7474
try {
75-
Double d = Double.valueOf(value);
76-
if ((d.isInfinite() || d.isNaN()) && !in.isLenient()) {
77-
throw new MalformedJsonException(
78-
"JSON forbids NaN and infinities: " + d + "; at path " + in.getPreviousPath());
79-
}
80-
return d;
81-
} catch (NumberFormatException doubleE) {
82-
throw new JsonParseException(
83-
"Cannot parse " + value + "; at path " + in.getPreviousPath(), doubleE);
75+
return Long.parseLong(value);
76+
} catch (NumberFormatException e) {
77+
return parseAsDouble(value, in);
8478
}
8579
}
8680
}
81+
82+
private Number parseAsDouble(String value, JsonReader in) throws IOException {
83+
try {
84+
Double d = Double.valueOf(value);
85+
if ((d.isInfinite() || d.isNaN()) && !in.isLenient()) {
86+
throw new MalformedJsonException(
87+
"JSON forbids NaN and infinities: " + d + "; at path " + in.getPreviousPath());
88+
}
89+
return d;
90+
} catch (NumberFormatException e) {
91+
throw new JsonParseException(
92+
"Cannot parse " + value + "; at path " + in.getPreviousPath(), e);
93+
}
94+
}
8795
},
8896

8997
/**

0 commit comments

Comments
 (0)