diff --git a/gson/src/main/java/com/google/gson/JsonPrimitive.java b/gson/src/main/java/com/google/gson/JsonPrimitive.java index 5e95d5a82b..1ed3b95590 100644 --- a/gson/src/main/java/com/google/gson/JsonPrimitive.java +++ b/gson/src/main/java/com/google/gson/JsonPrimitive.java @@ -203,6 +203,17 @@ public float getAsFloat() { */ @Override public long getAsLong() { + + if (isNumber()) { + final BigInteger val = getAsBigInteger(); + + if (val.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) { + throw new NumberFormatException("Expected a Long but was " + getAsNumber()); + } else if (val.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0) { + throw new NumberFormatException("Expected a Long but was " + getAsNumber()); + } + } + return isNumber() ? getAsNumber().longValue() : Long.parseLong(getAsString()); } @@ -214,6 +225,17 @@ public long getAsLong() { */ @Override public short getAsShort() { + + if (isNumber()) { + final BigInteger val = getAsBigInteger(); + + if (val.compareTo(BigInteger.valueOf(Short.MAX_VALUE)) > 0) { + throw new NumberFormatException("Expected a Short but was " + getAsNumber()); + } else if (val.compareTo(BigInteger.valueOf(Short.MIN_VALUE)) < 0) { + throw new NumberFormatException("Expected a Short but was " + getAsNumber()); + } + } + return isNumber() ? getAsNumber().shortValue() : Short.parseShort(getAsString()); } @@ -225,11 +247,39 @@ public short getAsShort() { */ @Override public int getAsInt() { + + if (isNumber()) { + final BigInteger val = getAsBigInteger(); + + if (val.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) { + throw new NumberFormatException("Expected an Integer but was " + getAsNumber()); + } else if (val.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0) { + throw new NumberFormatException("Expected an Integer but was " + getAsNumber()); + } + } + return isNumber() ? getAsNumber().intValue() : Integer.parseInt(getAsString()); } + /** + * convenience method to get this element as a primitive byte. + * + * @return get this element as a primitive byte. + * @throws NumberFormatException if the value contained is not a valid integer. + */ @Override public byte getAsByte() { + + if (isNumber()) { + final BigInteger val = getAsBigInteger(); + + if (val.compareTo(BigInteger.valueOf(Byte.MAX_VALUE)) > 0) { + throw new NumberFormatException("Expected a Byte but was " + getAsNumber()); + } else if (val.compareTo(BigInteger.valueOf(Byte.MIN_VALUE)) < 0) { + throw new NumberFormatException("Expected a Byte but was " + getAsNumber()); + } + } + return isNumber() ? getAsNumber().byteValue() : Byte.parseByte(getAsString()); } diff --git a/gson/src/test/java/com/google/gson/JsonParserTest.java b/gson/src/test/java/com/google/gson/JsonParserTest.java index cc18238be4..aebfe1c57d 100644 --- a/gson/src/test/java/com/google/gson/JsonParserTest.java +++ b/gson/src/test/java/com/google/gson/JsonParserTest.java @@ -19,6 +19,7 @@ import java.io.CharArrayReader; import java.io.CharArrayWriter; import java.io.StringReader; +import java.math.BigInteger; import junit.framework.TestCase; @@ -98,6 +99,81 @@ public void testParseReader() { assertEquals("c", e.getAsJsonObject().get("b").getAsString()); } + public void testParseLongToInt() { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("foo", 10000000000L); + + try { + jsonObject.get("foo").getAsInt(); + fail(); + } catch (NumberFormatException expected) { + } + } + + public void testParseIntegerTypes() { + + JsonObject jsonObject = new JsonObject(); + + jsonObject.addProperty("bigIntegerU", BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.valueOf(200L)) ); + jsonObject.addProperty("bigIntegerL", BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.valueOf(200L)) ); + jsonObject.addProperty("longU", Integer.MAX_VALUE+143L); + jsonObject.addProperty("longL", Integer.MIN_VALUE-143L); + jsonObject.addProperty("integerU", Short.MAX_VALUE+32); + jsonObject.addProperty("integerL", Short.MIN_VALUE-32); + jsonObject.addProperty("shortU", Byte.MAX_VALUE+17); + jsonObject.addProperty("shortL", Byte.MIN_VALUE-17); + + try { + jsonObject.get("bigIntegerU").getAsLong(); + fail("Big Integer values greater than Long.MAX_VALUE should not parse as a Long"); + } catch (NumberFormatException expected) { + } + + try { + jsonObject.get("bigIntegerL").getAsLong(); + fail("Big Integer values smaller than Long.MIN_VALUE should not parse as a Long"); + } catch (NumberFormatException expected) { + } + + try { + jsonObject.get("longU").getAsInt(); + fail("Long values larger than Integer.MAX_VALUE should not parse as an Integer"); + } catch (NumberFormatException expected) { + } + + try { + jsonObject.get("longL").getAsInt(); + fail("Long values smaller than Integer.MIN_VALUE should not parse as an Integer"); + } catch (NumberFormatException expected) { + } + + try { + jsonObject.get("integerU").getAsShort(); + fail("Integer values larger than Short.MAX_VALUE should not parse as a Short"); + } catch (NumberFormatException expected) { + } + + try { + jsonObject.get("integerL").getAsShort(); + fail("Integer values smaller than Short.MIN_VALUE should not parse as a Short"); + } catch (NumberFormatException expected) { + } + + try { + jsonObject.get("shortU").getAsByte(); + fail("Short values larger than Byte.MAX_VALUE should not parse as a Byte"); + } catch (NumberFormatException expected) { + } + + try { + jsonObject.get("shortL").getAsByte(); + fail("Short values smaller than Byte.MIN_VALUE should not parse as a Byte"); + } catch (NumberFormatException expected) { + } + + assertTrue(jsonObject.isJsonObject()); + } + public void testReadWriteTwoObjects() throws Exception { Gson gson = new Gson(); CharArrayWriter writer = new CharArrayWriter();