Parse all JSON numbers as either BigDecimal or BigInteger. From there we can properly convert into the proper primitive type if need be. This reduces the chance of losing precision with floating point numbers.
This commit is contained in:
parent
628a2c5b86
commit
d5319d9e84
|
@ -207,21 +207,12 @@ final class JsonParser implements JsonParserConstants {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
Number n;
|
Number n;
|
||||||
if (exppart != null) {
|
if (exppart != null || fracpart != null) {
|
||||||
fracpart = (fracpart == null) ? "" : fracpart;
|
fracpart = (fracpart == null) ? "" : fracpart;
|
||||||
|
exppart = (exppart == null) ? "" : exppart;
|
||||||
n = new java.math.BigDecimal(intpart + fracpart + exppart);
|
n = new java.math.BigDecimal(intpart + fracpart + exppart);
|
||||||
} else if (fracpart != null) {
|
|
||||||
n = new Double(intpart + fracpart);
|
|
||||||
} else {
|
} else {
|
||||||
// See if the number fits in an integer, or long
|
n = new java.math.BigInteger(intpart);
|
||||||
// Use BigInteger only if it is big enough.
|
|
||||||
if (intpart.length() < 10) {
|
|
||||||
n = new Integer(intpart);
|
|
||||||
} else if (intpart.length() < 19) {
|
|
||||||
n = new Long(intpart);
|
|
||||||
} else {
|
|
||||||
n = new java.math.BigInteger(intpart);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
{if (true) return new JsonPrimitive(n);}
|
{if (true) return new JsonPrimitive(n);}
|
||||||
throw new Error("Missing return statement in function");
|
throw new Error("Missing return statement in function");
|
||||||
|
|
|
@ -150,21 +150,12 @@ private JsonPrimitive JsonNumber() :
|
||||||
intpart=JsonInt() [ fracpart=JsonFrac() ] [ exppart=JsonExp() ]
|
intpart=JsonInt() [ fracpart=JsonFrac() ] [ exppart=JsonExp() ]
|
||||||
{
|
{
|
||||||
Number n;
|
Number n;
|
||||||
if (exppart != null) {
|
if (exppart != null || fracpart != null) {
|
||||||
fracpart = (fracpart == null) ? "" : fracpart;
|
fracpart = (fracpart == null) ? "" : fracpart;
|
||||||
|
exppart = (exppart == null) ? "" : exppart;
|
||||||
n = new java.math.BigDecimal(intpart + fracpart + exppart);
|
n = new java.math.BigDecimal(intpart + fracpart + exppart);
|
||||||
} else if (fracpart != null) {
|
|
||||||
n = new Double(intpart + fracpart);
|
|
||||||
} else {
|
} else {
|
||||||
// See if the number fits in an integer, or long
|
n = new java.math.BigInteger(intpart);
|
||||||
// Use BigInteger only if it is big enough.
|
|
||||||
if (intpart.length() < 10) {
|
|
||||||
n = new Integer(intpart);
|
|
||||||
} else if (intpart.length() < 19) {
|
|
||||||
n = new Long(intpart);
|
|
||||||
} else {
|
|
||||||
n = new java.math.BigInteger(intpart);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return new JsonPrimitive(n);
|
return new JsonPrimitive(n);
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,6 +253,22 @@ public class PrimitiveTest extends TestCase {
|
||||||
BigDecimal actual = gson.fromJson("1.55", BigDecimal.class);
|
BigDecimal actual = gson.fromJson("1.55", BigDecimal.class);
|
||||||
assertEquals(expected, actual);
|
assertEquals(expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testBigDecimalPreservePrecisionSerialization() {
|
||||||
|
String expectedValue = "1.000";
|
||||||
|
BigDecimal obj = new BigDecimal(expectedValue);
|
||||||
|
String actualValue = gson.toJson(obj);
|
||||||
|
|
||||||
|
assertEquals(expectedValue, actualValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testBigDecimalPreservePrecisionDeserialization() {
|
||||||
|
String json = "1.000";
|
||||||
|
BigDecimal expected = new BigDecimal(json);
|
||||||
|
BigDecimal actual = gson.fromJson(json, BigDecimal.class);
|
||||||
|
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
public void testBigDecimalAsStringRepresentationDeserialization() {
|
public void testBigDecimalAsStringRepresentationDeserialization() {
|
||||||
String doubleValue = "0.05E+5";
|
String doubleValue = "0.05E+5";
|
||||||
|
|
Loading…
Reference in New Issue
Block a user