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:
Joel Leitch 2008-11-18 20:26:15 +00:00
parent 628a2c5b86
commit d5319d9e84
3 changed files with 22 additions and 24 deletions

View File

@ -207,21 +207,12 @@ final class JsonParser implements JsonParserConstants {
;
}
Number n;
if (exppart != null) {
if (exppart != null || fracpart != null) {
fracpart = (fracpart == null) ? "" : fracpart;
exppart = (exppart == null) ? "" : exppart;
n = new java.math.BigDecimal(intpart + fracpart + exppart);
} else if (fracpart != null) {
n = new Double(intpart + fracpart);
} else {
// See if the number fits in an integer, or long
// 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);
}
n = new java.math.BigInteger(intpart);
}
{if (true) return new JsonPrimitive(n);}
throw new Error("Missing return statement in function");

View File

@ -150,21 +150,12 @@ private JsonPrimitive JsonNumber() :
intpart=JsonInt() [ fracpart=JsonFrac() ] [ exppart=JsonExp() ]
{
Number n;
if (exppart != null) {
if (exppart != null || fracpart != null) {
fracpart = (fracpart == null) ? "" : fracpart;
exppart = (exppart == null) ? "" : exppart;
n = new java.math.BigDecimal(intpart + fracpart + exppart);
} else if (fracpart != null) {
n = new Double(intpart + fracpart);
} else {
// See if the number fits in an integer, or long
// 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);
}
n = new java.math.BigInteger(intpart);
}
return new JsonPrimitive(n);
}

View File

@ -253,6 +253,22 @@ public class PrimitiveTest extends TestCase {
BigDecimal actual = gson.fromJson("1.55", BigDecimal.class);
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() {
String doubleValue = "0.05E+5";