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 @Override
public BigInteger getAsBigInteger() { 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; package com.google.gson;
import java.math.BigInteger;
/** /**
* This class holds a number value that is lazily converted to a specific number type * 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 @Override
public int intValue() { 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 @Override
public long longValue() { public long longValue() {
return Long.parseLong(value); try {
return Long.parseLong(value);
} catch (NumberFormatException e) {
return new BigInteger(value).longValue();
}
} }
@Override @Override

View File

@ -38,6 +38,9 @@ import java.math.BigInteger;
* @author Joel Leitch * @author Joel Leitch
*/ */
public class PrimitiveTest extends TestCase { 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; private Gson gson;
@Override @Override
@ -757,4 +760,68 @@ public class PrimitiveTest extends TestCase {
fail(); fail();
} catch (JsonSyntaxException expected) {} } 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());
}
} }