Gson和泛型擦除的解决方法

最近小伙伴给安卓端写了接口,返回的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;
        }
    };
}
}

如果有疑问的话,欢迎留言

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值