使用Gson解析泛型类型

在程序中访问网络的时候返回的Json有时候是固定的形式,我们所需要的json信息是以嵌套的形式给出的,比如
User info:

{
    "result_code":"4000",
    "result_msg":"接受数据正常",
    "json_msg":{
        "user_name":"jack",
        "user_age":15
    }
}

Book info:

{
    "result_code":"4000",
    "result_msg":"接受数据正常",
    "json_msg":{
        "book_name":"Java编程思想",
        "book_price":"108.00"
    }
}

如果我们直接用Gson解析的话,要有对应的实体类才行,比如要解析上面的两个Json的话,就要有两个类

public class UsreInfoBean {
    public String result_code;
    public String result_msg;
    public UserInfo json_msg;
}

public class BookInfoBean {
    public String result_code;
    public String result_msg;
    public BookInfo json_msg;
}

另外还需要UserInfo和BookInfo两个类:

public class UserInfo {
    public String user_name;
    public int user_age;
}

public class BookInfo{
    public String book_name;
    public String book_price;
}

这样的话每个Json都要对应两个类,很繁琐,另外如果Json比较多的话,会产生很多类,而这些类有一半都是多余的,维护起来也很麻烦。
观察UserInfoBean和BookInfoBean两个类,可以发现这两个类中的成员变量除了json_msg字段的类型不一样,其他的都完全一样,如果能把这连个类统一成一个类的话就能解决类多余的问题。Java的泛型恰好可以解决这个问题。上面的连个类用泛型可以写为:

public class InfoBean {
    public String result_code;
    public String result_msg;
    public T json_msg;
}

此时,UserInfoBean和BookInfoBean两个类就可以写成InfoBean和InfoBean,不管有多上类都可以写成这种形式。
试着我们常用的Gson用法去去解析json,

String json = ...; //对应上面的User info的json
//下面代码在android studio中会报错
InfoBean userInfo = new Gson().fromJson(json, InfoBean.class);

上面的代码并不能运行,原因是InfoBean是泛型,并不能直接获取class类型。通过android studio的代码提示功能可以看到Gson的fromJson()方法解析String类型的json有两种:

Object fromJson(Sting, Class<Object>)
Object fromJson(String, Type)

第一个方法就是我们一般常用的,接受class类型, 第二个方法接受一个Type类型,Type类型一般与与泛型的类型推断有关,查阅这个方法的文档可以发现这个方法就是用来处理泛型类型的,文档中介绍需要用TypeToken来获取泛型的type类型,并且给出了具体的用法:

Type typeOfT = new TypeToken>(){}.getType();

按照上面的形式现在我们来处理InfoBean:

String json = ...; //对应上面的User info的json
Type type = new TypeToken>(){}.getType();
InfoBean userInfo = new Gson.fromJson(json, type);

现在就可以正确的获取userInfo对象了。

另外,一般情况下,在json对应的实体类中,类的成员变量的名字要和json对应字段的名字一样才能正确解析,比如上面的User info的json中的”result_code”字段在InfoBean类中要有result_code成员变量来对应。而我们在开发安卓程序的时候一般习惯用驼峰命名法,即result_code字段一般习惯用resultCode来命名。

Gson对这种情况也是有处理的,只要使用一个注解就可以解决问题:
@SerializedName("result_code")

注解中的名字对应json中的字段名字,这时我们就可以对实体类中的成员变量随便命名了。对InfoBean加上注解后:

public class InfoBean {
    @SerializedName("result_code")
    public String resultCode;

    @SerializedName("result_msg")
    public String resultMsg;

    @SerializedName("json_msg")
    public T resultObj;
}

这样我们在代码中访问json实体类的时候,代码的阅读性就会提高很多。

你可能感兴趣的:(开发经验)