JSON反序列化:java.lang.Double不能强制转换为java.lang.Long
以下内容在控制台上工作并打印42:JSON反序列化:java.lang.Double不能强制转换为java.lang.Long,java,json,gson,Java,Json,Gson,以下内容在控制台上工作并打印42: long l = (new Gson()).fromJson("42", Long.class); System.out.printf("[%d]\n", l); 以下内容也适用并打印相同内容: final Type TYPE = new TypeToken<Long>() {}.getType(); long l = (new Gson()).fromJson("42", TYPE); …在源中标记的行处 完整轨迹非常浅,只有这一行: [
long l = (new Gson()).fromJson("42", Long.class);
System.out.printf("[%d]\n", l);
以下内容也适用并打印相同内容:
final Type TYPE = new TypeToken<Long>() {}.getType();
long l = (new Gson()).fromJson("42", TYPE);
…在源中标记的行处
完整轨迹非常浅,只有这一行:
[java] Exception in thread "main" java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Long
[java] at FooMain.main(FooMain.java:18)
为什么会发生这种情况,为什么在编译时没有检测到问题
我已经用gson 2.8.0测试过了
我认为这可能与泛型类型信息在运行时被擦除有关,因此可能无法在运行时基于提供的泛型类型构造TypeToken
经过进一步的实验,我得到的异常与我所做的相同:
private static Object fromJSON(String json) {
final Type TYPE = new TypeToken<Object>() {}.getType();
Object rv = (new Gson()).fromJson(json, TYPE);
return rv;
}
public static void main(String args[]) throws Exception {
long l = (long) fromJSON("42");
}
私有静态对象fromJSON(字符串json){
final-Type=new-TypeToken(){}.getType();
Object rv=(new Gson()).fromJson(json,类型);
返回rv;
}
公共静态void main(字符串args[])引发异常{
long l=(long)fromJSON(“42”);
}
…以上在运行时生成完全相同的跟踪,这与类型擦除解释一致。所以我想我们只能等到Java9了。简短的回答是“类型擦除”
较长的答案是,代码的通用版本——newtypetoken()
call——不会记录每个调用的不同类型值。T
的值仅在编译时使用,在运行时不可用,并且只有一个运行时版本的代码必须处理可以传递给它的每个值
这样做的结果是Gson最终试图解析类型为“
T
”的值,并且无法知道T
实际上是长的。因此,它根据内容进行猜测,内容是一个数字,它与数字类型一起使用,具有最广泛的可能值范围-Double
捕获异常并打印堆栈跟踪-可能有用我认为您关于类型擦除的想法可能非常正确:/
[java] Exception in thread "main" java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Long
[java] at FooMain.main(FooMain.java:18)
private static Object fromJSON(String json) {
final Type TYPE = new TypeToken<Object>() {}.getType();
Object rv = (new Gson()).fromJson(json, TYPE);
return rv;
}
public static void main(String args[]) throws Exception {
long l = (long) fromJSON("42");
}