美文网首页
Gson泛型

Gson泛型

作者: yesyourhighness | 来源:发表于2018-11-15 11:32 被阅读0次

一、为何封装,如何封装

通常我们解析的json格式为

// data 为 object 的情况
{"code":"0","message":"success","data":{}}
// data 为 array 的情况
{"code":"0","message":"success","data":[]}

第一种的对应的Java类型为 Result<XXX> ,第二种为 Result<List<XXX>>

1、为何封装

  • new TypeToken<XXX>(){}麻烦,麻烦
  • 不同的地方每进行一次 new TypeToken<XXX>(){} 操作都会生成一个新的类
  • 对于任意类XXX都只有两种情况new TypeToken<Result<XXX>>(){}new TypeToken<Result<List<XXX>>>(){}
  • 方便统一管理

2、如何封装

从上面的我们可以知道,最简单的方法就是提供两个方法分别对应data为Array和Object的情况并接收一个参数,即告知XXX的类型,自动将完成new TypeToken<XXX>(){}与new TypeToken<Result<List<XXX>>>(){}的过程。

方法原型:

// 处理 data 为 object 的情况
public static <T> Result<T> fromJsonObject(Reader reader, Class<T> clazz) {}
// 处理 data 为 array 的情况
public static <T> Result<List<T>> fromJsonArray(Reader reader, Class<T> clazz){}

如果尝试这么封装

public static <T> Result<List<T>> fromJsonArray(Reader reader) {
    Type type = new TypeToken<Result<List<T>>>(){}.getType();
    return GSON.fromJson(reader, type);
}

上面的写法虽然代码不会报错,但运行结果肯定是不对的,因为这里的T 其实是一个TypeVariable,他在运行时并不会变成我们想要的XXX,所以通过TypeToken 得到的 泛型信息只是"Result<List<T>>"

二、如何解决?

一句话:自己生成type
Type是Java中所有类型的父接口,在1.8以前是一个空接口,自1.8起多了个getTypeName()方法,下面有ParameterizedTypeGenericArrayTypeWildcardTypeTypeVariable 几个接口,以及Class类。这几个接口在本次封装过程中只会用到 ParameterizedType ,所以简单说一下:

ParameterizedType简单说来就是形如“ 类型<> ”的类型,如:Map<String,User>。下面就以 Map<String,User>为例讲一下里面各个方法的作用。

public interface ParameterizedType extends Type {
     // 返回Map<String,User>里的String和User,所以这里返回[String.class,User.clas]
    Type[] getActualTypeArguments(); 
    // Map<String,User>里的Map,所以返回值是Map.class
    Type getRawType();
    // 用于这个泛型上中包含了内部类的情况,一般返回null
    Type getOwnerType(); 
}

知道了这些需要的泛型,下面完成之前留下的空方法。

1、实现一个简易的 ParameterizedType
public class ParameterizedTypeImpl implements ParameterizedType {
    private final Class raw;
    private final Type[] args;
    public ParameterizedTypeImpl(Class raw, Type[] args) {
        this.raw = raw;
        this.args = args != null ? args : new Type[0];
    }
    @Override
    public Type[] getActualTypeArguments() {
        return args;
    }
    @Override
    public Type getRawType() {
        return raw;
    }
    @Override
    public Type getOwnerType() {return null;}
}
2、生成Gson需要的泛型
2.1解析data是Object的情况
public static <T> Result<T> fromJsonObject(Reader reader, Class<T> clazz) {
    Type type = new ParameterizedTypeImpl(Result.class, new Class[]{clazz});
    return GSON.fromJson(reader, type);
}
2.2解析data是array的情况
public static <T> Result<List<T>> fromJsonArray(Reader reader, Class<T> clazz) {
    // 生成List<T> 中的 List<T>
    Type listType = new ParameterizedTypeImpl(List.class, new Class[]{clazz});
    // 根据List<T>生成完整的Result<List<T>>
    Type type = new ParameterizedTypeImpl(Result.class, new Type[]{listType});
    return GSON.fromJson(reader, type);
}

相关文章

  • Android Gson 解析泛型报错

    当用Gson解析泛型会报以下错误: com.google.gson.internal.LinkedTreeMap ...

  • Gson泛型

    一、为何封装,如何封装 通常我们解析的json格式为 第一种的对应的Java类型为 Result ,第二...

  • Gson解析泛型数据类型

    Gson解析泛型类型:Res Type type = new TypeToken(){}.getTyp...

  • GSON

    需要掌握的知识点 GSON的基本用法 属性重命名 @SerializedName 注解的使用 GSON使用泛型 利...

  • Android中泛型的应用(二)

    背景感谢并参考[怪盗kidou]的《搞定Gson泛型封装》 。上一篇《 Java基础--Android中泛型的应用...

  • Gson解析泛型

    做网络请求的时候肯定要封装回调,我这里就传了泛型,但是出了个问题是Gson没办法直接解析泛型,如果直接解析的话,不...

  • Gson Advanced — 泛型

    原文链接:Gson Advanced — Generics原文出自:Norman Peitek译者:無名無 本文将...

  • gson解析泛型

    list = gson.fromJson(jsonString,newTypeToken>(){}.getType...

  • Gson解析泛型

    1、json对应的model是T 2、json对应的model是List 3、json对应的model是 m...

  • TypeReference获取泛型参数

    使用Gson、Jackson或Fastjson反序列化泛型时,需要传递泛型的真实类型,所以一般都通过集成TypeR...

网友评论

      本文标题:Gson泛型

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