From d5319d9e840b2c7237ca435f50c50ffbe7dce507 Mon Sep 17 00:00:00 2001 From: Joel Leitch Date: Tue, 18 Nov 2008 20:26:15 +0000 Subject: [PATCH] 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. --- .../main/java/com/google/gson/JsonParser.java | 15 +++------------ gson/src/main/javacc/JsonParser.jj | 15 +++------------ .../google/gson/functional/PrimitiveTest.java | 16 ++++++++++++++++ 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/gson/src/main/java/com/google/gson/JsonParser.java b/gson/src/main/java/com/google/gson/JsonParser.java index b338718d..a86037b6 100755 --- a/gson/src/main/java/com/google/gson/JsonParser.java +++ b/gson/src/main/java/com/google/gson/JsonParser.java @@ -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"); diff --git a/gson/src/main/javacc/JsonParser.jj b/gson/src/main/javacc/JsonParser.jj index 9ded1d33..4e408d2b 100755 --- a/gson/src/main/javacc/JsonParser.jj +++ b/gson/src/main/javacc/JsonParser.jj @@ -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); } diff --git a/gson/src/test/java/com/google/gson/functional/PrimitiveTest.java b/gson/src/test/java/com/google/gson/functional/PrimitiveTest.java index ef080ed4..65a64643 100644 --- a/gson/src/test/java/com/google/gson/functional/PrimitiveTest.java +++ b/gson/src/test/java/com/google/gson/functional/PrimitiveTest.java @@ -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";