zoukankan      html  css  js  c++  java
  • Android okHttp网络请求之Json解析

      前言:

      前面两篇文章介绍了基于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解析了。

  • 相关阅读:
    SQL Server Audit监控触发器状态
    SQL Server 数据变更时间戳(timestamp)在复制中的运用
    SQL Server 更改跟踪(Chang Tracking)监控表数据
    SQL Server 变更数据捕获(CDC)监控表数据
    SQL Server 事件通知(Event notifications)
    SQL Server 堆表行存储大小(Record Size)
    SQL Server DDL触发器运用
    SQL Server 默认跟踪(Default Trace)
    SQL Server 创建数据库邮件
    SQL Server 跨网段(跨机房)FTP复制
  • 原文地址:https://www.cnblogs.com/whoislcj/p/5533548.html
Copyright © 2011-2022 走看看