在开发使用Gson序列化对象并反序列化它们的应用程序时遇到了问题。但是,我遇到了一个问题,我无法解释原因,一段时间后,我将问题缩小到这个SSCCE:
import com.google.gson.Gson;
/**
* demonstrates the issue at hand
*/
public class Probs {
public Probs () {
//holds the byte array form of the JSON data
byte[] info = new byte[1];
//get the JSON for a data object and store it in the byte array
Gson gson = new Gson();
Data before = new Data(1);
info = gson.toJson(before).getBytes();
//reassemble the JSON data as a string
String json = new String(info);
System.out.println("JSON string: " + json);
//reconstruct the Data object from the JSON data
Data after = gson.fromJson(json, Data.class);
//attempt to get the "num" value and convert it to an integer
Object val = after.getNum();
System.out.println("Class name: " + val.getClass().getName()); //is java.lang.Double (why isn't it java.lang.Object?)
Integer num = (Integer)val; //produces "java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer"
System.out.println("Number: " + num);
}
public static void main(String[] args) {
new Probs();
}
}
/**
* holds the one piece of data
*/
class Data {
Object num;
public Data(int num) {
this.num = num;
System.out.println("Object value: " + this.num);
}
public Object getNum () {
return this.num;
}
}
我确实阅读了this post,但似乎没有任何可接受的答案。由于我在应用程序中使用它的方式,我需要让Data对象将其数据存储为Object,并能够将其稍后转换为其他类型。当我反序列化数据对象并调用它的getNum()时,我认为应该返回一个Object(因为这是它的返回类型)。在我的应用程序中,我需要能够将该类型转换为Integer。但是,JVM似乎将Object(val)转换为Double,因为getClass()显示它是Double而不是Object。然后,当我尝试通过强制转换将其转换为整数时,它会失败,因为它显然是Double而不是Object。
我的问题是:为什么val是Double而不是Object(我不理解的是什么)?
感谢您的帮助
答案 0 :(得分:2)
问题是JSON规范,以及您正在做什么。
JSON spec仅指定单数字类型,可以包含小数点和小数部分:
2.4。编号
数字表示与大多数数字相似 编程语言。数字包含一个整数分量 可以使用可选的减号作为前缀,后面可以是 分数部分和/或指数部分。
在解析/映射JSON时,JSON解析器可以自行决定如何处理该数值类型。
在您的情况下,您的Data
班级num
定义为Object
。这使得Gson没有提示您希望JSON数字类型映射到哪个特定的Java数字类型。无论JSON中的数字是否包含小数+分数,Gson的作者决定使用Double
。
当你考虑一个整数可以表示为double时,这实际上是完全合理的,但不是相反。使用单一类型而不是解析数字并确定它是int还是double提供了一致的行为。
目前还不清楚为什么你没有在Integer
对象int
中使用num
(或Data
},如果这是你期望/需要的话。你声明你需要转换为Integer
“稍后”,这意味着对象首先可以是Integer
;任何其他的铸造尝试都会失败。