前言:

前面两篇文章介绍了基于okHttp的post、get请求,以及文件的上传下载,今天主要介绍一下如何和Json解析一起使用?如何才能提高开发效率?

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解析的更多相关文章

  1. Android okHttp网络请求之Get/Post请求

    前言: 之前项目中一直使用的Xutils开源框架,从xutils 2.1.5版本使用到最近的xutils 3.0,使用起来也是蛮方便的,只不过最近想着完善一下app中使用的开源框架,由于Xutils里 ...

  2. Android okHttp网络请求之文件上传下载

    前言: 前面介绍了基于okHttp的get.post基本使用(http://www.cnblogs.com/whoislcj/p/5526431.html),今天来实现一下基于okHttp的文件上传. ...

  3. Android okHttp网络请求之缓存控制Cache-Control

    前言: 前面的学习基本上已经可以完成开发需求了,但是在项目中有时会遇到对请求做个缓存,当没网络的时候优先加载本地缓存,基于这个需求我们来学习一直okHttp的Cache-Control. okHttp ...

  4. Android okHttp网络请求之Retrofit+Okhttp+RxJava组合

    前言: 通过上面的学习,我们不难发现单纯使用okHttp来作为网络库还是多多少少有那么一点点不太方便,而且还需自己来管理接口,对于接口的使用的是哪种请求方式也不能一目了然,出于这个目的接下来学习一下R ...

  5. C#网络请求与JSON解析

    最新学校的海康摄像头集控平台(网页端)不能在win10里登录,我寻思着拿海康的c# demo直接改. 首先得解决权限问题,每个教师任教不同年级,只能看到自己所在年级的设备,涉及到登录,在此记录一下C# ...

  6. iOS 自己封装的网络请求,json解析的类

    基本上所有的APP都会涉及网络这块,不管是用AFNetWorking还是自己写的http请求,整个网络框架的搭建很重要. 楼主封装的网络请求类,包括自己写的http请求和AFNetWorking的请求 ...

  7. Flutter网络请求与JSON解析

    本文介绍如何在Flutter中创建HTTP网络请求和对请求的json string进行类型解析. 网络请求 官方使用的是用dart io中的HttpClient发起的请求,但HttpClient本身功 ...

  8. 网络请求之JSON解析

    <一>JSON的基本知识 什么是JSON:JSON的全称是JavaScript Object Notation(JavaScript对象符号),是目前使用最广泛的数据交换格式,具有跨平台. ...

  9. Android okHttp网络请求库详解

    okhttp 是一个 Java 的 HTTP+SPDY 客户端开发包,同时也支持 Android.需要Android 2.3以上. 特点 OKHttp是Android版Http客户端.非常高效,支持S ...

随机推荐

  1. C语言 · 乘法表

    问题描述 输出九九乘法表. 输出格式 输出格式见下面的样例.乘号用"*"表示. 样例输出 下面给出输出的前几行:1*1=12*1=2 2*2=43*1=3 3*2=6 3*3=94 ...

  2. 《Django By Example》第一章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:本人目前在杭州某家互联网公司工作, ...

  3. 【初学python】使用python调用monkey测试

    目前公司主要开发安卓平台的APP,平时测试经常需要使用monkey测试,所以尝试了下用python调用monkey,代码如下: import os apk = {'j': 'com.***.test1 ...

  4. bootstrap-fileinput 简单使用

    bootstrap-fileinput 是一款图片/文件上传 bootstrap 插件,简单示例代码: <!DOCTYPE html> <html> <head> ...

  5. springmvc SSM shiro redis 后台框架 多数据源 代码生成器

    A集成代码生成器 [正反双向(单表.主表.明细表.树形表,开发利器)+快速构建表单 下载地址    ; freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本,处理类 ...

  6. SymmetricDS 快速和灵活的数据库复制

    开始谈谈开源的SymmetricDS,谈谈实际使用中,遇到的一些问题和解决办法.持续更新: SymmetricDS 快速和灵活的数据库复制 实际使用 和 埋过的坑 (一)知识篇 SymmetricDS ...

  7. 《Note --- Unreal --- MemPro (CONTINUE... ...)》

    Mem pro 是一个主要集成内存泄露检测的工具,其具有自身的源码和GUI,在GUI中利用"Launch" button进行加载自己待检测的application,目前支持的平台为 ...

  8. linux压缩和解压缩命令大全

    .tar 解包:tar zxvf FileName.tar 打包:tar czvf FileName.tar DirName ------------------------------------- ...

  9. Forward+ Rendering Framework

    近几天啃各种新技术时又一个蛋疼的副产品...额,算是把AMD的Forward+ Sample抄了一遍吧. 其实个人感觉这个AMD大肆宣传的Forward+跟Intel很早之前提的Tiled-Based ...

  10. 保护ASP.NET 应用免受 CSRF 攻击

    CSRF是什么? CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/ ...