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 ...
随机推荐
- Html Agility Pack 解析Html
Hello 好久不见 哈哈,今天给大家分享一个解析Html的类库 Html Agility Pack.这个适用于想获取某网页里面的部分内容.今天就拿我的Csdn的博客列表来举例. 打开页面 用Fir ...
- Java多线程基础学习(二)
9. 线程安全/共享变量——同步 当多个线程用到同一个变量时,在修改值时存在同时修改的可能性,而此时该变量只能被赋值一次.这就会导致出现“线程安全”问题,这个被多个线程共用的变量称之为“共享变量”. ...
- JavaScript性能优化
如今主流浏览器都在比拼JavaScript引擎的执行速度,但最终都会达到一个理论极限,即无限接近编译后程序执行速度. 这种情况下决定程序速度的另一个重要因素就是代码本身. 在这里我们会分门别类的介绍J ...
- hadoop 2.7.3本地环境运行官方wordcount
hadoop 2.7.3本地环境运行官方wordcount 基本环境: 系统:win7 虚机环境:virtualBox 虚机:centos 7 hadoop版本:2.7.3 本次先以独立模式(本地模式 ...
- RxJS + Redux + React = Amazing!(译二)
今天,我将Youtube上的<RxJS + Redux + React = Amazing!>的后半部分翻译(+机译)了下来,以供国内的同学学习,英文听力好的同学可以直接看原版视频: ht ...
- 了不起的 nodejs-TwitterWeb 案例 bug 解决
了不起的nodejs算是一本不错的入门书,不过书中个别案例存在bug,按照书中源码无法做出和书中相同效果,原本兴奋的心情掺杂着些许失落. 现在我们看一下第七章HTTP,一个Twitter Web客户端 ...
- PHP的学习--RSA加密解密
PHP服务端与客户端交互或者提供开放API时,通常需要对敏感的数据进行加密,这时候rsa非对称加密就能派上用处了. 举个通俗易懂的例子,假设我们再登录一个网站,发送账号和密码,请求被拦截了. 密码没加 ...
- 代码的坏味道(21)——中间人(Middle Man)
坏味道--中间人(Middle Man) 特征 如果一个类的作用仅仅是指向另一个类的委托,为什么要存在呢? 问题原因 对象的基本特征之一就是封装:对外部世界隐藏其内部细节.封装往往伴随委托.但是人们可 ...
- jQuery可自动播放动画焦点图插件Koala
Koala是一款简单而实用的jQuery焦点图幻灯片插件,焦点图不仅可以在播放图片的时候让图片有淡入淡出的动画效果,而且图片可以自动播放.该jQuery焦点图的每一张图片都可以设置文字描述,并浮动在图 ...
- CSS三个定位——常规、浮动、绝对定位
.dage { width: 868px; background: #5B8C75; border: 10px solid #A08C5A; margin-top: -125px; margin-le ...