使用Gson读取数据时避免从整数进行双重转换

时间:2018-05-21 05:44:22

标签: java gson typetoken

我在airospike中使用json保存数据:

new Gson().toJson(data)

在阅读时,我使用的是typetoken:

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

上述转换的问题是,所有整数都转换为双精度数。如何停止转换?

1 个答案:

答案 0 :(得分:3)

这是Gson中一个众所周知的问题。 默认情况下,Gson始终将声明为Object的JSON数字反序列化为Double,从而导致长整数值的某些精度损失。 Object序列化程序/反序列化程序无法通过设计覆盖,因此您无法更改其行为。 如果您可以将声明类型缩小到Number,Gson会将数字反序列化为com.google.gson.internal.LazilyParsedNumber,其中包含一个支持字符串,并且可以将其解析为任何&#34;内置的&#34;懒惰的数字类型(例如,longValue()doubleValue()可以返回适当的值)。 如果你可以进一步缩小范围,那就更好了。 例如:

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());
    }
}

将产生以下输出:

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

简单来说,至少从Gson 2.8.4开始,你不能为Object做到这一点,但是如果它适合你,你可以指定一个更具体的类型。 我试图fix这个问题,但修复程序仍处于预审状态。