Android okHttp网络请求之Json解析
前言:
前面两篇文章介绍了基于okHttp的post、get请求,以及文件的上传下载,今天主要介绍一下如何和Json解析一起使用?如何才能提高开发效率?
okHttp相关文章地址:
- Android okHttp网络请求之Get/Post请求
- Android okHttp网络请求之文件上传下载
- Android okHttp网络请求之Json解析
- Android okHttp网络请求之缓存控制Cache-Control
- Android okHttp网络请求之Retrofit+Okhttp组合
关于Json解析:
本文的Json解析采用阿里巴巴的FastJson 解析,也可以采用Gson解析,两者之间的对比请参考文章Android之json解析(FastJson Gson 对比)(http://www.cnblogs.com/whoislcj/p/5468420.html)。
关于泛型:
本文将采用json统一泛型解析,阅读本文之前请先对java泛型知识有一定的了解。
关于反射机制:
本文会采用Java的反射机制来解析泛型对象Class<?>,阅读本文之前请先对Java发射机制知识有一定的了解。
代码实现:
1.)首先我们声明一个TypeInfo.java类用来封装泛型相关属性
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; public class TypeInfo {
//Type泛型对象类型
private Class<?> componentType;
//Type所属对象类型
private Class<?> rawType;
//type
private Type type; private TypeInfo(Class<?> rawType, Class<?> componentType) { this.componentType = componentType;
this.rawType = rawType;
} public static TypeInfo createArrayType(Class<?> componentType) {
return new TypeInfo(Array.class, componentType);
} public static TypeInfo createNormalType(Class<?> componentType) {
return new TypeInfo(null, componentType);
} public static TypeInfo createParameterizedType(Class<?> rawType, Class<?> componentType) {
return new TypeInfo(rawType, componentType);
} public TypeInfo(Type type) {
this.type = type;
if (type instanceof ParameterizedType) {
//返回 Type 对象,表示声明此类型的类或接口。
this.rawType = (Class<?>) ((ParameterizedType) type).getRawType();
//getActualTypeArguments()返回表示此类型实际类型参数的 Type 对象的数组。
Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
this.componentType = (Class<?>) actualTypeArguments[0];
// typeReference=new TypeReference<Map<componentType,componentType>>(){}; } else if (type instanceof GenericArrayType) {
//返回 Type 对象,表示声明此类型的类或接口。
this.rawType = Array.class;
// 表示一种元素类型是参数化类型或者类型变量的数组类型
this.componentType = (Class<?>) ((GenericArrayType) type).getGenericComponentType();
} else {
this.componentType = (Class<?>) type;
}
} public Type getType() {
return type;
} public Class<?> getComponentType() {
return componentType;
} public Class<?> getRawType() {
return rawType;
} }
2.)声明ReqClassUtils.java类 用于通过反射机制获取泛型对象的TypeInfo
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; public class ReqClassUtils { public static TypeInfo getCallbackGenericType(Class<?> clazz) {
//获得带有泛型的父类
Type genericSuperclass = clazz.getGenericSuperclass();//Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。
TypeInfo type = getGetnericType(genericSuperclass);
if (type == null) {
Type[] genericInterfaces = clazz.getGenericInterfaces();
if (genericInterfaces != null && genericInterfaces.length > 0) {
type = getGetnericType(genericInterfaces[0]);
}
}
return type;
} private static TypeInfo getGetnericType(Type type) {
if (type != null && type instanceof ParameterizedType) {
//getActualTypeArguments获取参数化类型的数组,泛型可能有多个
Type[] args = ((ParameterizedType) type).getActualTypeArguments();
if (args != null && args.length > 0) {
return new TypeInfo(args[0]);
}
}
return null;
}
}
3.)接下来重点来了,声明一个json解析工具类ReqJsonUtils.java,主要用于通过TypeInfo相关属性进行不同类型的json解析
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map; import static com.alibaba.fastjson.JSON.parseObject; public class ReqJsonUtils { //基本类型映射关系Map
private static final Map primitiveWrapperTypeMap = new HashMap(8); static {
//添加基本类型
primitiveWrapperTypeMap.put(Boolean.class, boolean.class);
primitiveWrapperTypeMap.put(Byte.class, byte.class);
primitiveWrapperTypeMap.put(Character.class, char.class);
primitiveWrapperTypeMap.put(Double.class, double.class);
primitiveWrapperTypeMap.put(Float.class, float.class);
primitiveWrapperTypeMap.put(Integer.class, int.class);
primitiveWrapperTypeMap.put(Long.class, long.class);
primitiveWrapperTypeMap.put(Short.class, short.class);
} /**
* 将JSON字符串转换成指定的用户返回值类型
*
* @param type
* @param jsonData
* @return
* @throws JSONException
*/
public static <T> T parseHttpResult(TypeInfo type, String jsonData) throws JSONException {
// 处理Void类型的返回值
if (Void.class.isAssignableFrom(type.getComponentType())) {
return null;
}
//获取当前type的数据类型
Class<?> rawType = type.getRawType();
//是否是Array
boolean isArray = rawType != null && Array.class.isAssignableFrom(rawType);
//是否是Collection
boolean isCollection = rawType != null && Collection.class.isAssignableFrom(rawType);
//是否是Map
boolean isMap = rawType != null && Map.class.isAssignableFrom(rawType);
//获取泛型类型
Class<?> componentType = type.getComponentType();
//声明结果对象
T result = null;
if (isCollection) {//处理collection
result = (T) JSON.parseArray(jsonData, componentType);
} else if (isArray) {//处理array
result = (T) JSON.parseArray(jsonData, componentType).toArray();
} else if (isMap) {//处理Map
result = (T) JSONObject.parseObject(jsonData, type.getType());
} else if (componentType.isAssignableFrom(String.class)) {//处理字符串返回值
return (T) jsonData;
} else {
// 接口的返回类型如果是简单类型,则会封装成为一个json对象,真正的对象存储在value属性上
if (isPrimitiveOrWrapper(componentType)) {
result = (T) parseObject(jsonData);
} else {
//处理自定义对象
result = (T) parseObject(jsonData, componentType);
}
}
return result;
} /**
* 判断是否是基本数据类型
*
* @param clazz
* @return
*/
public static boolean isPrimitiveOrWrapper(Class clazz) {
return (clazz.isPrimitive() || isPrimitiveWrapper(clazz));
} /**
* 判断是否是基本数据类型
*
* @param clazz
* @return
*/
public static boolean isPrimitiveWrapper(Class clazz) {
return primitiveWrapperTypeMap.containsKey(clazz);
}
}
如何使用?
1.)实现解析
TypeInfo typeInfo = ReqClassUtils.getCallbackGenericType(callBack.getClass());
callBack.onReqSuccess(ReqJsonUtils.parseHttpResult(typeInfo, jsonData));
2.)发送请求
HashMap<String, String> paramsMap = new HashMap<>();
paramsMap.put("sourceType", "2");
paramsMap.put("sourceDesc", "[Android]" + Build.VERSION.RELEASE + "[Mobel]" + Build.BRAND + " " + Build.MODEL + Build.DEVICE);
HashMap<String, String> params = dealStringBody(paramsMap);
RequestManager.getInstance(this).requestAsyn("xxx/actionUrl", RequestManager.TYPE_POST_JSON, params, new ReqCallBack<String>() { @Override
public void onReqSuccess(String result) {
request_tv.setText(result);
} @Override
public void onReqFailed(String errorMsg) { }
});
3.)支持类型
new ReqCallBack<List<Object>>();//集合collection
new ReqCallBack<Map<String, User>>();//map
new ReqCallBack<Void>();//Void
new ReqCallBack<Long>();//基础类型
小结:如此一来发送请求到解析数据变得So easy !用流行的一句广告语来说的话,那就是老板再也不用担心我搞不定网络请求和json解析了。
Android okHttp网络请求之Json解析的更多相关文章
- Android okHttp网络请求之Get/Post请求
前言: 之前项目中一直使用的Xutils开源框架,从xutils 2.1.5版本使用到最近的xutils 3.0,使用起来也是蛮方便的,只不过最近想着完善一下app中使用的开源框架,由于Xutils里 ...
- Android okHttp网络请求之文件上传下载
前言: 前面介绍了基于okHttp的get.post基本使用(http://www.cnblogs.com/whoislcj/p/5526431.html),今天来实现一下基于okHttp的文件上传. ...
- Android okHttp网络请求之缓存控制Cache-Control
前言: 前面的学习基本上已经可以完成开发需求了,但是在项目中有时会遇到对请求做个缓存,当没网络的时候优先加载本地缓存,基于这个需求我们来学习一直okHttp的Cache-Control. okHttp ...
- Android okHttp网络请求之Retrofit+Okhttp+RxJava组合
前言: 通过上面的学习,我们不难发现单纯使用okHttp来作为网络库还是多多少少有那么一点点不太方便,而且还需自己来管理接口,对于接口的使用的是哪种请求方式也不能一目了然,出于这个目的接下来学习一下R ...
- C#网络请求与JSON解析
最新学校的海康摄像头集控平台(网页端)不能在win10里登录,我寻思着拿海康的c# demo直接改. 首先得解决权限问题,每个教师任教不同年级,只能看到自己所在年级的设备,涉及到登录,在此记录一下C# ...
- iOS 自己封装的网络请求,json解析的类
基本上所有的APP都会涉及网络这块,不管是用AFNetWorking还是自己写的http请求,整个网络框架的搭建很重要. 楼主封装的网络请求类,包括自己写的http请求和AFNetWorking的请求 ...
- Flutter网络请求与JSON解析
本文介绍如何在Flutter中创建HTTP网络请求和对请求的json string进行类型解析. 网络请求 官方使用的是用dart io中的HttpClient发起的请求,但HttpClient本身功 ...
- 网络请求之JSON解析
<一>JSON的基本知识 什么是JSON:JSON的全称是JavaScript Object Notation(JavaScript对象符号),是目前使用最广泛的数据交换格式,具有跨平台. ...
- Android okHttp网络请求库详解
okhttp 是一个 Java 的 HTTP+SPDY 客户端开发包,同时也支持 Android.需要Android 2.3以上. 特点 OKHttp是Android版Http客户端.非常高效,支持S ...
随机推荐
- js中参数不对应问题
因为js是一种弱类型的编程语言,对数据类型的要求没有其他编程语言的要求严格,所以在定义函数的时候不需要像java和C#一样对其传入参数的类型进行定义.那么传入参数的个数有没有影响呢?今天小猪就做了个实 ...
- Asp.net Boilerplate源码中NotNullAttribute的用处
看Asp.net Boilerplate 1.1.3.0源码时发现有一个NotNullAttribute的定义和27处的引用,就是不知道它的作用,当然顾名思义是可以的,就是不知道它是怎么判断的,在哪里 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(75)-微信公众平台开发-用户管理
系列目录 前言 本节主要是关注者(即用户)和用户组的管理,微信公众号提供了用户和用户组的管理,我们可以在微信公众号官方里面进行操作,添加备注和标签,以及移动用户组别,同时,微信公众号也提供了相应的接口 ...
- Paypal开发中遇到请求被中止: 未能创建 SSL/TLS 安全通道及解决方案
最近在基于ASP.NET上开发了Paypal支付平台,在ASP.NET开发的过程中没有遇到这个问题,但是引用到MVC开发模式中的时候就出现了"未能创建 SSL/TLS 安全通道及解决方案&q ...
- 操作系统篇-分段机制与GDT|LDT
|| 版权声明:本文为博主原创文章,未经博主允许不得转载. 一.前言 在<操作系统篇-浅谈实模式与保护模式>中提到了两种模式,我们说在操作系统中,其实大部分时间是待在保护模式中的. ...
- 自己实现简单Spring Ioc
IoC则是一种 软件设计模式,简单来说Spring通过工厂+反射来实现IoC. 原理简单说明: 其实就是通过解析xml文件,通过反射创建出我们所需要的bean,再将这些bean挨个放到集合中,然后对外 ...
- 用Kotlin创建第一个Android项目(KAD 01)
原文标题:Create your first Android project using Kotlin (KAD 01) 作者:Antonio Leiva 时间:Nov 21, 2016 原文链接:h ...
- Atitit godaddy 文件权限 root权限设置
Atitit godaddy 文件权限 root权限设置 1. ubuntu需要先登录,再su切换到root1 2. sudo 授权许可使用的su,也是受限制的su1 3. ubuntu默认吗roo ...
- 在Ubuntu下搭建Spark群集
在前一篇文章中,我们已经搭建好了Hadoop的群集,接下来,我们就是需要基于这个Hadoop群集,搭建Spark的群集.由于前面已经做了大量的工作,所以接下来搭建Spark会简单很多. 首先打开三个虚 ...
- MongoDB学习笔记三—增删改文档上
插入insert 单条插入 > db.foo.insert({"bar":"baz"}) WriteResult({ }) 批量插入 > db.fo ...