最近小伙伴给安卓端写了接口,返回的json格式大概如下
{
“data”: [
{
“content”: “每天跑5公里”,
“taskId”: 1,
“title”: “xxxtitle”,
“task_icon_type”: 1
}
],
“code”: “200”,
“msg”: “xxxx”
}
一个code,一个msg,还有一个data,data可以根据返回不同的object
我就想着写一个GsonUtil类配合BaseBean,去解析。
首先是BaseBean,配合泛型,如下所示:
public class BaseBean< T> implements Serializable{
private String msg;
private String code;
private T data;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
接着,写GsonUtil,方便解析,如下所示:
public class GsonUtil {
//Json转字符串
public static <T> T toString(String response,Class<T> classZ) {
return new Gson().fromJson(response,classZ);
}
}
接着,我便开开心心进行测试。可以使用了。
接着,我进行一下扩展,想要获取data的类型
于是我写成这样子
public static T toString(String response,Class classZ){
try {
Log.w(“TYPE”,new TypeToken(){}.getType()+”“);
return new Gson().fromJson(response,new TypeToken(){}.getType());
}catch (Throwable e){
return null;
}
}
结果呢,抛出异常
java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.example.vizax.with.bean.BaseBean
上网找了一些资料,最后发现
Java泛型的实现机制,使用了泛型的代码在运行期间相关的泛型参数的类型会被擦除,我们无法在运行期间获知泛型参数的具体类型(所有的泛型类型在运行时都是Object类型)
意思就是说,我们传入一个泛型T,然后gson在解析的时候,会把泛型参数的类型擦除,那么我们就没办法获得参数的类型了。所以也就报错了
接着找了一些资料,发现比较靠谱的是使用ParameterizedType,如下所示
/**
* ParameterizedType对象,对于Object、接口和原始类型返回null,对于数组class则是返回Object.class。
* ParameterizedType是表示带有泛型参数的类型的Java类型,
* JDK1.5引入了泛型之后,Java中所有的Class都实现了Type接口,ParameterizedType则是继承了Type接口,
* 所有包含泛型的Class类都会实现这个接口。
* @param raw
* @param args
* @return
public static ParameterizedType type(final Class raw,final Type... args){
return new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return args;
}
@Override
public Type getRawType() {
return raw;
}
@Override
public Type getOwnerType() {
return null;
}
};
}
就是说对于带有泛型的类,返回一个ParameterizedType对象,对于Object、接口和原始类型返回null,对于数组class则是返回Object.class。ParameterizedType是表示带有泛型参数的类型的Java类型。
故最后代码如下
public class GsonUtil {
//Json转字符串,输出T的类型
/*public static <T> T toString(String response,Class<T> classZ){
Gson gson = new Gson();
Type objectType = type(BaseBean.class,classZ);
return gson.fromJson(response,objectType);
}*/
/*public static <T> T toString(String response,Class<T> classZ) {
return new Gson().fromJson(response,classZ);
}*/
//会报错,因为Gson进行序列化、反序列化的时候会将泛型擦除,所有的类都变成Object,故得不到所需要的泛型。
public static <T> T toString(String response,Class<T> classZ){
try {
Log.w("TYPE",new TypeToken<T>(){}.getType()+"");
return new Gson().fromJson(response,new TypeToken<T>(){}.getType());
}catch (Throwable e){
return null;
}
}
/**
* ParameterizedType对象,对于Object、接口和原始类型返回null,对于数组class则是返回Object.class。
* ParameterizedType是表示带有泛型参数的类型的Java类型,
* JDK1.5引入了泛型之后,Java中所有的Class都实现了Type接口,ParameterizedType则是继承了Type接口,
* 所有包含泛型的Class类都会实现这个接口。
* @param raw
* @param args
* @return
*/
public static ParameterizedType type(final Class raw,final Type... args){
return new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return args;
}
@Override
public Type getRawType() {
return raw;
}
@Override
public Type getOwnerType() {
return null;
}
};
}
}
如果有疑问的话,欢迎留言