一:用于测试的类
User类
import lombok.Data; import lombok.experimental.Accessors; /** * @author silentdoer * @version 1.0 */ @Data @Accessors(chain = true) public class User { private String name; private String gender; }
AppResult类
import lombok.Data; import lombok.experimental.Accessors; /** * @author silentdoer * @version 1.0 */ @Data @Accessors(chain = true) public class AppResult<T> { private int code; private T data; }
二:Fastjson测试代码
String str = "{\"code\":100,\"data\":{\"gender\":\"男\",\"name\":\"中文\"}}"; AppResult<User> o = JSON.parSEObject("{\"code\":100,\"name\":\"中文\"}}",AppResult.class); System.out.println(o); System.out.println(o.getData().getClass()); // flag
在flag行会报java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to User
原因:因为Java的泛型擦除机制,无法像C#一样使用类似AppResult<User>.class,而AppResult.class中的T虽然在字节码里也叫T,但是会被jvm认为是Object的任意子类;
结论:Fastjson检测到要转换的类型是泛型时将会把那部分JSON字符串转换为fastjson的JSONObject对象赋值给data,因此这里报转换错误
三:Gson测试代码
Gson gson = new Gson(); AppResult<User> appResult = gson.fromJson(str,AppResult.class); System.out.println(appResult); System.out.println(appResult.getData().getClass());
也是报异常:java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to User
结论:Gson如果检测到要反序列化的对象类型是泛型,那么将用一个gson自己的LinkedTreeMap来存储
四:对于Jackson也是一样
五:实现泛型的转换方式
1.对于Fastjson或Gson都是可以有个TypeToken一样的东西,不过这里用个更简单的方法:
Fastjson:
AppResult<User> o = JSON.parSEObject("{\"code\":100,new AppResult<User>(){}.getClass());
Gson:Gson似乎不行,只能用TypeToken来实现;
Fastjson可以的原理,其实就是因为泛型类虽然无法保留泛型的具体类型,但是其子类在具体化泛型后是可以保留的,因此new一个泛型类的空实现的子类,然后getClass()即可;