Revised Gson to refuse to deserialize floating point numbers into integer types.

This is probably a break from the past: previous versions of Gson allowed truncating a floating point into a long or int. However, it wasn't consistent in this behavior. It disallowed converting a BigDecimal value into BigInteger, int or long. Refusing to deserialize such values is aligned with fail-fast approach of uncovering bugs.
This commit is contained in:
Inderjeet Singh 2011-05-04 23:26:22 +00:00
parent ce79e16f7a
commit 0bcd1b341f
3 changed files with 85 additions and 3 deletions

View File

@ -213,7 +213,8 @@ public final class JsonPrimitive extends JsonElement {
*/
@Override
public BigInteger getAsBigInteger() {
return value instanceof BigInteger ? (BigInteger) value : new BigInteger(value.toString());
return value instanceof BigInteger ?
(BigInteger) value : new BigInteger(value.toString());
}
/**

View File

@ -15,6 +15,8 @@
*/
package com.google.gson;
import java.math.BigInteger;
/**
* This class holds a number value that is lazily converted to a specific number type
*
@ -30,12 +32,24 @@ final class LazilyParsedNumber extends Number {
@Override
public int intValue() {
return Integer.parseInt(value);
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
try {
return (int) Long.parseLong(value);
} catch (NumberFormatException nfe) {
return new BigInteger(value).intValue();
}
}
}
@Override
public long longValue() {
return Long.parseLong(value);
try {
return Long.parseLong(value);
} catch (NumberFormatException e) {
return new BigInteger(value).longValue();
}
}
@Override

View File

@ -38,6 +38,9 @@ import java.math.BigInteger;
* @author Joel Leitch
*/
public class PrimitiveTest extends TestCase {
private static final BigInteger MAX_INT_VALUE = new BigInteger("2147483647");
private static final BigInteger MAX_LONG_VALUE = new BigInteger("9223372036854775807");
private Gson gson;
@Override
@ -757,4 +760,68 @@ public class PrimitiveTest extends TestCase {
fail();
} catch (JsonSyntaxException expected) {}
}
public void testDeserializingDecimalPointValuesAsIntegerFails() {
try {
gson.fromJson("1.0", Integer.class);
fail();
} catch (JsonParseException expected) {
}
}
public void testDeserializingBigDecimalAsIntegerFails() {
try {
gson.fromJson("-122.08e-213", Integer.class);
fail();
} catch (JsonParseException expected) {
}
}
public void testDeserializingBigIntegerAsInteger() {
String bigIntegerValue = "12121211243123245845384534687435634558945453489543985435";
int actual = gson.fromJson(bigIntegerValue, Integer.class);
int expected = new BigInteger(bigIntegerValue).and(MAX_INT_VALUE).intValue();
assertEquals(expected, actual);
}
public void testDeserializingBigIntegerAsLong() {
String bigIntegerValue = "12121211243123245845384534687435634558945453489543985435";
long actual = gson.fromJson(bigIntegerValue, long.class);
long expected = new BigInteger(bigIntegerValue).and(MAX_LONG_VALUE).longValue();
assertEquals(expected, actual);
}
public void testDeserializingBigDecimalAsLongFails() {
try {
gson.fromJson("-122.08e-2132", long.class);
fail();
} catch (JsonParseException expected) {
}
}
public void testDeserializingBigDecimalAsFloat() {
String json = "-122.08e-2132332";
float actual = gson.fromJson(json, float.class);
assertEquals(-0.0f, actual);
}
public void testDeserializingBigDecimalAsDouble() {
String json = "-122.08e-2132332";
double actual = gson.fromJson(json, double.class);
assertEquals(-0.0d, actual);
}
public void testDeserializingBigDecimalAsBigIntegerFails() {
try {
gson.fromJson("-122.08e-213", BigInteger.class);
fail();
} catch (JsonParseException expected) {
}
}
public void testDeserializingBigIntegerAsBigDecimal() {
BigDecimal actual =
gson.fromJson("12121211243123245845384534687435634558945453489543985435", BigDecimal.class);
assertEquals("12121211243123245845384534687435634558945453489543985435", actual.toPlainString());
}
}