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:
parent
ce79e16f7a
commit
0bcd1b341f
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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() {
|
||||||
|
try {
|
||||||
return Integer.parseInt(value);
|
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() {
|
||||||
|
try {
|
||||||
return Long.parseLong(value);
|
return Long.parseLong(value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return new BigInteger(value).longValue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user