我编写了以下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()
}
}
但是,似乎在反序列化期间未调用此适配器。是否可以强制将整数反序列化为整数?
A new feature added看起来可能有助于解决此问题
答案 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感兴趣。