• 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解析了。

  • 相关阅读:
    BGP笔记
    IS-IS笔记
    MAC ACL、RACL和VACL
    MPLS笔记
    OSPF笔记
    RIP笔记
    组播浅谈
    如何查看本机是否是虚拟机
    python中逻辑运算符“+”的特殊之处
    劳动成本持续增高,中国企业如何自救?精益化生产提升企业附加值
  • 原文地址:https://www.cnblogs.com/whoislcj/p/5533548.html
Copyright © 2020-2023  润新知