反序列化数字时防止Gson将整数转换为小数

时间:2019-03-21 18:17:51

标签: java json groovy gson

我编写了以下Spock测试,以演示在反序列化包含数字的JSON对象时发生的问题

class GsonFactorySpec extends Specification {

    private Gson gson = GsonFactory.instance.gsonInstance

    private String JSON = '{"number": 2}'

    def 'deserialize a JSON document with an integer value to a Map'() {

        when:
        Map deserialized = gson.fromJson(JSON, Map)

        then:
        deserialized.number instanceof Integer
    }
}

测试失败,因为该数字反序列化为值为2.0而不是Double 2的Integer

在创建Gson实例的工厂类中,我尝试为Number的实例注册适配器。

@Singleton
class GsonFactory {

    private final JsonSerializer<Number> numberSerializer = new JsonSerializer<Number>() {
        @Override
        JsonElement serialize(Number number, Type type, JsonSerializationContext context) {
            Integer intValue = number.toInteger()
            intValue == number ? new JsonPrimitive(intValue) : new JsonPrimitive(number)
        }
    }

    Gson getGsonInstance() {
        new GsonBuilder().serializeNulls().registerTypeHierarchyAdapter(
            Number, numberSerializer).create()
    }
} 

但是,似乎在反序列化期间未调用此适配器。是否可以强制将整数反序列化为整数?

更新

Gson版本2.8.5中的

A new feature added看起来可能有助于解决此问题

1 个答案:

答案 0 :(得分:0)

您缺少正确的类型信息:Map.class没有提供类型参数设置,因此Gson使用了String键和Object值(Object(反序列化不能而是被覆盖,因此这就是对象层次结构策略不起作用的原因。在Java中,它将类似于:

private static final Type mapStringToNumberType = new TypeToken<Map<String, Number>>() {}.getType();

public static void main(final String... args) {
    @SuppressWarnings("unchecked")
    final Map<String, Number> map = gson.fromJson("{\"number\": 2}", mapStringToNumberType);
    System.out.println(map.get("number"));
}

您可能也对解决类似问题的陈旧PR感兴趣。