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

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

//网络请求接口回调,这里使用了泛型,不考虑用interface
package 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;
    }

}

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

你可能感兴趣的:(android,泛型,网络)