简体   繁体   中英

Avoid double conversion from integer while reading data using Gson

I am saving data using json in aerospike:

new Gson().toJson(data)

While reading, I am using typetoken:

Type type = new TypeToken<Map<String, Object>>() {
                        }.getType();
Map<String, Map<String, Object>> myMap = new Gson().fromJson(dataFromCache, type);

The issue with above conversion is, that all integers are converted into doubles. How can I stop the conversion?

This is a well-known issue in Gson. By default, Gson always deserializes JSON numbers that are declared as Object to Double causing some precision loss for long integer values. Object serializers/deserializers cannot be overridden by design, so you cannot change its behavior. If you can narrow down the declaration type to Number , Gson would deserialize the numbers to com.google.gson.internal.LazilyParsedNumber that holds a backing string and can parse it to any "built-in" numeric type lazily (say, longValue() and doubleValue() can return an appropriate value). If you can narrow down even more, it would work even better. Example:

final String json = "[1,4,9]";
final Iterable<? extends Type> types = ImmutableList.of(
        new TypeToken<Collection<Object>>() {}.getType(),
        new TypeToken<Collection<Number>>() {}.getType(),
        new TypeToken<Collection<Integer>>() {}.getType()
);
for ( final Type type : types ) {
    System.out.print(type);
    System.out.print(": ");
    System.out.println();
    for ( final Object value : gson.<Iterable<?>>fromJson(json, type) ) {
        System.out.print('\t');
        System.out.print(value);
        System.out.print(' ');
        System.out.println(value.getClass());
    }
}

would produce the following output:

java.util.Collection<java.lang.Object>: 
    1.0 class java.lang.Double
    4.0 class java.lang.Double
    9.0 class java.lang.Double
java.util.Collection<java.lang.Number>: 
    1 class com.google.gson.internal.LazilyParsedNumber
    4 class com.google.gson.internal.LazilyParsedNumber
    9 class com.google.gson.internal.LazilyParsedNumber
java.util.Collection<java.lang.Integer>: 
    1 class java.lang.Integer
    4 class java.lang.Integer
    9 class java.lang.Integer

Simply speaking, you cannot do it for Object s at least as of Gson 2.8.4, but you can specify a more concrete type if it's fine for you. I was trying to fix the issue, but the fix is still in the pre-review state.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM