我编写了以下 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
}
}
测试失败,因为数字被反序列化为 Double
值为 2.0 而不是 Integer
2.
在我创建 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在 Gson 2.8.5 版本中看起来可能有助于解决这个问题
最佳答案
您缺少正确的类型信息: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 感兴趣解决了类似的问题。
关于java - 防止Gson在反序列化数字时将整数转换为小数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55286855/