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

作者: esmark | 来源:发表于2017-11-28 10:27 被阅读0次

    在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泛型解析的解决方案

    相关文章

      网友评论

        本文标题:Gson解析时遇到的泛型擦除问题

        本文链接:https://www.haomeiwen.com/subject/ebrsbxtx.html