Android开发Java 杂谈android 开发程序员

Gson解析时遇到的泛型擦除问题

2017-11-28  本文已影响0人  esmark

在SharedPreferencesde的拓展使用:存储List的用法中,大家基本都能搜到下面这段代码:

public <T> List<T> getDataList(String tag) {  
        List<T> datalist = new ArrayList<T>();  
        String strJson = preferences.getString(tag, null);  
        if (null == strJson) {  
            return datalist;  
        }

        Gson gson = new Gson();  
        datalist = gson.fromJson(strJson, new TypeToken<List<T>>() {}.getType());

        return datalist;  
    }

但其实这段代码的使用是有问题的,我在使用这段代码获取保存的list时,提示Json解析错误,简单看了下,问题发生在下面这句代码:

datalist = gson.fromJson(strJson, new TypeToken<List<T>>() {}.getType()); 

这句在实际执行的时候,List<T>中的T并未传入实际的泛型参数,导致Gson按照LinkedTreeMap来解析JSON,以致发生了错误;

这就是一个在编译期泛型类型擦除所导致的问题;
相关泛型擦除的资料可参考:
Gson TypeToken with dynamic ArrayList item type
Java泛型-类型擦除

下面提供解决方案:
1.更改解析方式(推荐)

public <T> List<T> getDataList(String tag, Class<T> cls) {  
        List<T> datalist = new ArrayList<T>();
        String strJson = preferences.getString(tag, null);
        if (null == strJson) {  
            return datalist;  
        }

        JsonArray array = new JsonParser().parse(strJson).getAsJsonArray();  
        for(final JsonElement elem : array){  
            datalist.add(new Gson().fromJson(elem, cls));  
        }  
          
        return datalist;  
    }

2.增加一步对type的处理

public <T> List<T> getDataList(String tag, Class<T> cls) {  
        List<T> datalist = new ArrayList<T>();  
        String strJson = preferences.getString(tag, null);  
        if (null == strJson) {  
            return datalist;  
        }

        Gson gson = new Gson();
        Type type = new ListParameterizedType(cls);
        datalist = gson.fromJson(strJson, type);

        return datalist;  
    }

private static class ListParameterizedType implements ParameterizedType {
   private Type type;
   private ListParameterizedType(Type type) {
      this.type = type;
   }

   @Override
   public Type[] getActualTypeArguments() {
      return new Type[] {type};
   }

   @Override
   public Type getRawType() {
      return ArrayList.class;
   }

   @Override
   public Type getOwnerType() {
      return null;
   }

   // implement equals method too! (as per javadoc)
}

相关参考:
Gson解析Json数组遇到的泛型类型擦除问题

前两天利用GSON解析JSON串,碰到了Java 泛型擦除的问题

使用Gson解析Json数组遇到的泛型类型擦除问题解决方法

利用gson处理Java反射TypeToken泛型运行时类型擦除

gson处理泛型的问题

关于Gson泛型解析的解决方案

上一篇下一篇

猜你喜欢

热点阅读