如何使用gson解析泛型形参并返回相对应的类

来源:互联网 发布:网络引导安装系统 编辑:程序博客网 时间:2024/06/01 17:21

    在android实际开发中,我们在请求网络数据的时候,服务器返回的通常都是json字符串,我们需要将json转化成我们需要的类,当然这些通常是使用gson来完成的,过程大概就是要判断解析后的类是否存在,类是否有效,类字段是否有值,其实这些逻辑都差不多,所以就会导致有很多重复的地方,这个时候我就想到用泛型来处理这个过程。
    先看看我新建的项目空间:
项目空间
类文件介绍
HttpResponse.java

//网络请求数据所对应的java类//code:0表示请求数据成功;不为0则表示失败//msg:如果网络请求失败,代表失败原因//result:实际业务数据public class HttpResponse {    private String msg;    private String code;    private Object result;    public String getMsg() {        return msg;    }    public String getCode() {        return code;    }    public Object getResult() {        return result;    }    public void setMsg(String msg) {        this.msg = msg;    }    public void setCode(String code) {        this.code = code;    }    public void setResult(Object result) {        this.result = result;    }}

MyListener.java

//网络请求接口回调,这里使用了泛型,不考虑用interfacepackage study.fanxing.bean;public abstract class MyListener<T> {    public abstract void success(T t);    public abstract void fail(String msg);}

    Student.java和Teacher.java(这两个是业务类,为了方便测试,这两个类的字段都是一样的)

package study.fanxing.bean;public class Student {    private String name;    private String address;    private int age;    private String sex;    public Student() {    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getAddress() {        return address;    }    public void setAddress(String address) {        this.address = address;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public String getSex() {        return sex;    }    public void setSex(String sex) {        this.sex = sex;    }}

Test1.java

package study.fanxing.test;import com.google.gson.Gson;import study.fanxing.bean.HttpResponse;import study.fanxing.bean.MyListener;import study.fanxing.bean.Student;import study.fanxing.bean.Teacher;public class Test1 {    public static Gson gson=new Gson();    //模拟实际的网络请求,注意这里只传了一个参数    public static <T> void requestNetworkData(MyListener<T> listener) {        HttpResponse response=null;        try {            response=gson.fromJson(getJson(), HttpResponse.class);        }catch(Exception e) {            e.printStackTrace();        }        //数据解析并且请求成功        if(response!=null && response.getCode().equals("0")) {            String type=TTypeUtils.getTType(listener.getClass());            if(type!=null && type.length()>0) {                T t=null;                try {                    String json=gson.toJson(response.getResult());                    Class<T> clazz=(Class<T>) Class.forName(type);                    t=gson.fromJson(json, clazz);                }catch(Exception e) {                    e.printStackTrace();                }                if(t!=null)                    listener.success(t);                else                    showError(response, listener);            } else {                showError(response, listener);            }        } else {            showError(response, listener);        }    }    //处理请求错误,解析错误这种情况    private static void showError(HttpResponse response,MyListener listener) {        if(response!=null && response.getMsg()!=null && response.getMsg().length()>0)             listener.fail(response.getMsg());        else              listener.fail("网络错误");    }    //请求student接口    public static void testRequestStudent() {        requestNetworkData(new MyListener<Student>() {            @Override            public void success(Student student) {                // TODO Auto-generated method stub                System.out.println("student:");                System.out.println("name:"+student.getName());                System.out.println("sex:"+student.getSex());                System.out.println("address:"+student.getAddress());                System.out.println("age:"+student.getAge());            }            @Override            public void fail(String msg) {                // TODO Auto-generated method stub                System.out.println(msg);            }        });    }    //请求teacher接口    public static void testRequestTeacher() {        requestNetworkData(new MyListener<Teacher>() {            @Override            public void success(Teacher t) {                // TODO Auto-generated method stub                System.out.println("teacher:");                System.out.println("name:"+t.getName());                System.out.println("sex:"+t.getSex());                System.out.println("address:"+t.getAddress());                System.out.println("age:"+t.getAge());            }            @Override            public void fail(String msg) {                // TODO Auto-generated method stub                System.out.println(msg);            }        });    }    //生成测试json    public static void createJson() {        HttpResponse response=new HttpResponse();        response.setCode("0");        response.setMsg("成功");        Student student=new Student();        student.setName("张三");        student.setAddress("中国");        student.setAge(15);        student.setSex("男");        response.setResult(student);        System.out.println(gson.toJson(response));    }    public static String getJson() {        return "{\"msg\":\"成功\",\"code\":\"0\",\"result\":{\"name\":\"张三\",\"address\":\"中国\",\"age\":15,\"sex\":\"男\"}}";    }    public static void main(String[] args) {//      createJson();        testRequestStudent();        testRequestTeacher();    }}

TTypeUtils.java

package study.fanxing.test;import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;//这个类很关键,用来获取泛型类里面泛型的实际类型public class TTypeUtils {    public static String getTType(Class<?> clazz) {        Type mySuperClassType=clazz.getGenericSuperclass();        Type[] types=((ParameterizedType)mySuperClassType).getActualTypeArguments();        if(types!=null && types.length>0) {            String[] TType=types[0].toString().split(" ");            if(TType!=null && TType.length>1) {                return TType[1];            }        }        return null;    }}

那我们来看一下运行的效果:
运行效果
    从结果上看,已经正确的解析了json。从整个网络请求来看,只需要传入一个MyListener(T:具体的类类型,例如Student,Teacher)就可以获取实际的业务类,不需要每次都要判断一大推HttpResponse的逻辑,使用起来非常方便。当然如果返回的业务json是一个数组,我相信也可以做出来,大家可以自己试试。
    当然还有可以优化的地方,例如HttpResponse里面的result字段可以没有,可以在MyListener.java类里面定义result字段,这样使用android官方自带的JSONObject获取result:JSONObject.optString(“result”),这样使用起来会更方便。

0 0