如何使用gson解析泛型形参并返回相对应的类
2016-04-30 10:22
459 查看
在android实际开发中,我们在请求网络数据的时候,服务器返回的通常都是json字符串,我们需要将json转化成我们需要的类,当然这些通常是使用gson来完成的,过程大概就是要判断解析后的类是否存在,类是否有效,类字段是否有值,其实这些逻辑都差不多,所以就会导致有很多重复的地方,这个时候我就想到用泛型来处理这个过程。
先看看我新建的项目空间:
类文件介绍
HttpResponse.java
MyListener.java
Student.java和Teacher.java(这两个是业务类,为了方便测试,这两个类的字段都是一样的)
Test1.java
TTypeUtils.java
那我们来看一下运行的效果:
从结果上看,已经正确的解析了json。从整个网络请求来看,只需要传入一个MyListener(T:具体的类类型,例如Student,Teacher)就可以获取实际的业务类,不需要每次都要判断一大推HttpResponse的逻辑,使用起来非常方便。当然如果返回的业务json是一个数组,我相信也可以做出来,大家可以自己试试。
当然还有可以优化的地方,例如HttpResponse里面的result字段可以没有,可以在MyListener.java类里面定义result字段,这样使用android官方自带的JSONObject获取result:JSONObject.optString(“result”),这样使用起来会更方便。
先看看我新建的项目空间:
类文件介绍
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; } }
那我们来看一下运行的效果:
从结果上看,已经正确的解析了json。从整个网络请求来看,只需要传入一个MyListener(T:具体的类类型,例如Student,Teacher)就可以获取实际的业务类,不需要每次都要判断一大推HttpResponse的逻辑,使用起来非常方便。当然如果返回的业务json是一个数组,我相信也可以做出来,大家可以自己试试。
当然还有可以优化的地方,例如HttpResponse里面的result字段可以没有,可以在MyListener.java类里面定义result字段,这样使用android官方自带的JSONObject获取result:JSONObject.optString(“result”),这样使用起来会更方便。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件