美文网首页
原生org.json实现JSON数据与对象之间的转化

原生org.json实现JSON数据与对象之间的转化

作者: wuchao226 | 来源:发表于2021-04-02 14:42 被阅读0次

    在开发 SDK 时为了避免兼容性问题,不依赖三方解析库fastjson或者gson;这时我们需要使用android原生的json来自定义处理工具类;

    使用方法

    // Json字符串转为JavaBean
    String jsonString = "{"this":"jsonObjectString"}";
    JavaBean bean = JsonUtils.jsonToObject(jsonString, JavaBean.class);
    
    // Json字符串转为Java数组
    String jsonString = "[{"this":"jsonObjectString"},{"this":"jsonObjectString"}]";
    List<JavaBean> eventList = JsonUtils.jsonToObject(jsonString, new TypeReference<List<JavaBean>>() {});
    
    // JavaBean list 数组转为Json字符串
    List<JavaBean> mEventLists= new ArrayList<>();
    String eventStr = JsonUtils.toJSONString(mEventLists);
    
    // JavaBean对象转为Json字符串
    JavaBean bean=new JavaBean();
    String dataStr = JsonUtils.toJSONString(bean);
    
    import org.json.JSONArray;
    import org.json.JSONException;
    import org.json.JSONObject;
    
    /**
     * android 自带原生org.json 自定义JSON处理工具类
     */
    public class JsonUtils {
      /**
       * <p>对象/数组列表转JSON字符串</p>
       */
      public static String toJSONString(Object obj)
          throws JSONException, IllegalAccessException, IllegalArgumentException,
                 InvocationTargetException, NoSuchMethodException, SecurityException {
        if (obj == null) {
          return null;
        }
        return toJSONObject(obj).toString();
      }
    
      /**
       * <p>对list转为JSONArray,对对象转为JSONObject</p>
       */
      @SuppressWarnings("rawtypes")
      private static Object toJSONObject(Object object)
          throws JSONException, IllegalAccessException, IllegalArgumentException,
                 InvocationTargetException, NoSuchMethodException, SecurityException {
        if (object == null) {
          return null;
        }
        if (object instanceof JSONObject || object instanceof JSONArray) {
          return object;
        }
        // 基本数据类型非数组
        if (isBaseType(object.getClass()) && !object.getClass().isArray()) {
          return object;
        } else if (object instanceof Map) { //如果为Map
          Map map = (Map) object;
          JSONObject jsonObject = new JSONObject();
          for (Object key : map.keySet()) {
            Object value = map.get(key);
            jsonObject.put(String.valueOf(key), toJSONObject(value));
          }
          return jsonObject;
        } else if (object instanceof List) {// 为List
          List list = (List) object;
          JSONArray jsonArray = new JSONArray();
          for (Object obj : list) {
            jsonArray.put(toJSONObject(obj));
          }
          return jsonArray;
        } else if (object.getClass().isArray()) { // 为数组
          int length = Array.getLength(object);
          JSONArray jsonArray = new JSONArray();
          for (int i = 0; i < length; i++) {
            jsonArray.put(toJSONObject(Array.get(object, i)));
          }
          return jsonArray;
        } else {
          JSONObject jsonObject = new JSONObject();
          Class<?> clazz = object.getClass();
          parseObject(clazz, jsonObject, object);
          return jsonObject;
        }
      }
    
      private static void parseObject(Class<?> clazz, JSONObject jsonObject, Object object)
          throws IllegalAccessException, IllegalArgumentException,
                 InvocationTargetException, NoSuchMethodException, SecurityException, JSONException {
        if (clazz == null) {
          return;
        }
        // 通过反射获取到对象的所有属性
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
           // 判断如果给定field.getModifiers()参数包含transient修饰符
          if (Modifier.isTransient(field.getModifiers())) {
            continue;
          }
          // 获取属性的属性名
          String fieldName = field.getName();
          // getDeclaredMethod 获得类声明的命名的方法,但无法获取父类的字段,从类中获取了一个方法后,可以用 invoke() 方法来调用这个方法
          Method method = clazz.getDeclaredMethod("get" + captureName(fieldName));
          if (method != null) {
            jsonObject.put(fieldName, toJSONObject(method.invoke(object)));
          }
        }
        //clazz 的父类解析,继承关系时获取父类信息
        parseObject(clazz.getSuperclass(), jsonObject, object);
      }
    
      /**
       * 用get方法获取数据,首字母大写,如getName()
       */
      public static String captureName(String name) {
        char[] cs = name.toCharArray();
        //ascii 码表 ,如 n=110,N=78
        cs[0] -= 32;
        return String.valueOf(cs);
      }
    
      /**
       * <p>判断是否为基本类型并且不为数组</p>
       */
      private static boolean isBaseType(Class<?> clazz) {
        // isPrimitive 原始类型,isAssignableFrom 判断是否为某个类的类型
        if (clazz.isPrimitive()
            || String.class.isAssignableFrom(clazz)// clazz 是否能强转为 String 类型
            || Integer.class.isAssignableFrom(clazz)
            || Double.class.isAssignableFrom(clazz)
            || Float.class.isAssignableFrom(clazz)
            || Long.class.isAssignableFrom(clazz)
            || Boolean.class.isAssignableFrom(clazz)
            || Byte.class.isAssignableFrom(clazz)
            || Short.class.isAssignableFrom(clazz)
            || Character.class.isAssignableFrom(clazz)) {
          return true;
        } else {
          return false;
        }
      }
    
      /**
       * 将json字符串转化为对象列表
       *
       * @param json json字符串
       * 使用:
       * List<ActionEvent> eventList = JsonUtils.jsonToObject(jsonStr, new TypeReference<List<ActionEvent>>() {});
       * new TypeReference<List<ActionEvent>>() {} 创建了一个继承TypeReference>的匿名子类,在其构造函数中拿到了泛型对应Type
       */
      @SuppressWarnings("unchecked")
      public static <T> T jsonToObject(String json, TypeReference<T> typeReference) throws Exception {
        if (json == null || "".equals(json) || "".equals(json.trim())) {
          throw new Exception("入参json数据为空,请检查");
        }
        // 获取真实的泛型类型
        Type type = typeReference.genericParamType();
        Class<T> tClazz = (Class<T>) getTclazz(type);
        // 基本数据类型包括字符串 且不为 基本数据类型包括字符串数组
        if (isBaseType(tClazz) && !tClazz.isArray()) {
          throw new Exception("入参tClazz为基本类型,无法反序列化");
        }
        // 进行json串基本检查,判断是json对象还是JSONArray
        JSONObject jsonObject = null;
        JSONArray jsonArray = null;
        if (json.startsWith("{")) {
          jsonObject = new JSONObject(json);
        } else if (json.startsWith("[")) {
          jsonArray = new JSONArray(json);
        } else {
          throw new Exception("json数据非标准格式,请检查");
        }
        // 如果是JSONObject 直接返回
        if (JSONObject.class.isAssignableFrom(tClazz)) {
          return (T) jsonObject;
        }
        if (JSONArray.class.isAssignableFrom(tClazz)) {
          return (T) jsonArray;
        }
        if (tClazz.isArray()) {
          return createArr(jsonArray, tClazz);
        } else if (List.class.isAssignableFrom(tClazz)) {
          return (T) createList(type, jsonArray);
        } else if (Set.class.isAssignableFrom(tClazz)) {
          return (T) createSet(type, jsonArray);
        } else if (Map.class.isAssignableFrom(tClazz)) {
          return (T) createMap(type, jsonObject);
        } else {
          if (jsonObject == null) {
            throw new Exception("json数据格式无法转换到" + tClazz);
          }
          T t = createObject(jsonObject, tClazz);
          return t;
        }
      }
    
      /**
       * Json字符串转成对象
       *
       * @param json json字符串
       * @param tClazz 列表中的数据类型
       * @return 转化后的数据对象
       */
      @SuppressWarnings("unchecked")
      public static <T> T jsonToObject(String json, Class<T> tClazz) throws Exception {
        if (json == null || "".equals(json) || "".equals(json.trim())) {
          throw new Exception("入参json数据为空,请检查");
        }
        // 基本数据类型包括字符串 且不为 基本数据类型包括字符串数组
        if (isBaseType(tClazz) && !tClazz.isArray()) {
          throw new Exception("入参tClazz为基本类型,无法反序列化");
        }
        // 进行json串基本检查,判断是json对象还是JSONArray
        JSONObject jsonObject = null;
        JSONArray jsonArray = null;
        if (json.startsWith("{")) {
          // json是对象
          jsonObject = new JSONObject(json);
        } else if (json.startsWith("[")) {
          // json是JSONArray
          jsonArray = new JSONArray(json);
        } else {
          throw new Exception("json数据非标准格式,请检查");
        }
        // 如果是JSONObject 直接返回
        if (JSONObject.class.isAssignableFrom(tClazz)) {
          return (T) jsonObject;
        }
        if (JSONArray.class.isAssignableFrom(tClazz)) {
          return (T) jsonArray;
        }
        if (tClazz.isArray()) {// tClazz 表示数组类
          return createArr(jsonArray, tClazz);
        } else if (List.class.isAssignableFrom(tClazz)) {
          List<Object> list = new ArrayList<>();
          int length = jsonArray.length();
          for (int i = 0; i < length; i++) {
            list.add(jsonArray.get(i));
          }
          return (T) list;
        } else if (Set.class.isAssignableFrom(tClazz)) {
          Set<Object> set = new HashSet();
          int length = jsonArray.length();
          for (int i = 0; i < length; i++) {
            set.add(jsonArray.get(i));
          }
          return (T) set;
        }
        if (Map.class.isAssignableFrom(tClazz)) {
          Map<String, Object> map = new HashMap<>();
          Iterator<String> iterator = jsonObject.keys();
          while (iterator.hasNext()) {
            String key = iterator.next();
            map.put(key, jsonObject.get(key));
          }
          return (T) map;
        } else {
          if (jsonObject == null) {
            throw new Exception("json数据格式无法转换到" + tClazz);
          }
          T t = createObject(jsonObject, tClazz);
          return t;
        }
      }
    
      /**
       * 创建数组
       *
       * @param jsonArray jsonArray
       * @param tClazz tClazz 表示数组类
       */
      @SuppressWarnings("unchecked")
      private static <T> T createArr(JSONArray jsonArray, Class<T> tClazz) throws Exception {
        int len = jsonArray.length();
        // System.out.println(tClazz + " " + jsonArray);
        //创建具有指定组件类型和长度的新数组
        Object arr = Array.newInstance(tClazz.getComponentType(), len);
        for (int i = 0; i < len; i++) {
          Object obj = jsonArray.get(i);
          if (isBaseType(obj.getClass()) && !obj.getClass().isArray()) {
            Array.set(arr, i, (int) obj);
          } else if (obj instanceof JSONObject) {
            JSONObject jsonObjectNext = (JSONObject) obj;
            Array.set(arr, i, createObject(jsonObjectNext, tClazz.getComponentType()));
          } else if (obj instanceof JSONArray) {
            JSONArray jsonArrayNext = (JSONArray) obj;
            Array.set(arr, i, createArr(jsonArrayNext, tClazz.getComponentType()));
          }
        }
        return (T) arr;
      }
    
      private static <T> T createObject(JSONObject jsonObject, Class<T> tClazz) throws Exception {
        // 创建 tClazz 对象对应类的实例
        T t = tClazz.newInstance();
        assignField(jsonObject, tClazz, t);
        return t;
      }
    
      private static <T> void assignField(JSONObject jsonObject, Class<?> tClazz, T t) throws Exception {
        if (tClazz == null) {
          return;
        }
        // 获得 tClazz 类声明的所有字段
        Field[] fields = tClazz.getDeclaredFields();
        for (Field field : fields) {
          // 获取 此Field对象表示的字段的名称
          String fieldName = field.getName();
          // getType():返回一个Class 对象,它标识了此 Field 对象所表示字段的声明类型,如:String、Integer
          Class<?> filedClazz = field.getType();
          if (jsonObject.isNull(fieldName)) {
            continue;
          }
          // 获取字段fieldName对应的值value
          Object value = jsonObject.opt(fieldName);
          if (isBaseType(filedClazz) || JSONObject.class.isAssignableFrom(filedClazz)
              || JSONArray.class.isAssignableFrom(filedClazz)) {
            setterObject(tClazz, fieldName, filedClazz, t, value);
          } else if (filedClazz.isArray()) {
            if (value instanceof JSONArray) {
              JSONArray jsonArray = (JSONArray) value;
              Object arr = createArr(jsonArray, filedClazz);
              setterObject(tClazz, fieldName, filedClazz, t, arr);
            }
          } else if (List.class.isAssignableFrom(filedClazz)) {
            if (value instanceof JSONArray) {
              JSONArray jsonArray = (JSONArray) value;
              Type typeClass = field.getGenericType();
              List list = createList(typeClass, jsonArray);
              setterObject(tClazz, fieldName, filedClazz, t, list);
            }
          } else if (Set.class.isAssignableFrom(filedClazz)) {
            if (value instanceof JSONArray) {
              JSONArray jsonArray = (JSONArray) value;
              Type typeClass = field.getGenericType();
              Set set = createSet(typeClass, jsonArray);
              setterObject(tClazz, fieldName, filedClazz, t, set);
            }
          } else if (Map.class.isAssignableFrom(filedClazz)) {
            if (value instanceof JSONObject) {
              Type typeClass = field.getGenericType();
              JSONObject jsonObj = (JSONObject) value;
              Map map = createMap(typeClass, jsonObj);
              setterObject(tClazz, fieldName, filedClazz, t, map);
            }
          } else if (JSONObject.class.isAssignableFrom(filedClazz) || JSONArray.class.isAssignableFrom(filedClazz)) {
            setterObject(tClazz, fieldName, filedClazz, t, value);
          } else {
            JSONObject obj = (JSONObject) value;
            Object fieldObj = createObject(obj, filedClazz);
            setterObject(tClazz, fieldName, filedClazz, t, fieldObj);
          }
        }
        // 父类递归处理
        Class<?> superClazz = tClazz.getSuperclass();
        assignField(jsonObject, superClazz, t);
      }
    
      private static Class<?> getTclazz(Type type) {
        if (type instanceof Class) {
          return (Class<?>) type;
        } else {
          ParameterizedType parameterizedType = (ParameterizedType) type;
          // getRawType():返回原始类型Type
          return getTclazz(parameterizedType.getRawType());
        }
      }
    
      private static Map createMap(Type type, JSONObject jsonObject) throws Exception {
        Map<String, Object> map = new HashMap<>();
        ParameterizedType parameterizedType = (ParameterizedType) type;
        Type nextType = parameterizedType.getActualTypeArguments()[1];
        Class<?> itemKlacc = getTclazz(nextType);
        boolean flag = isBaseType(itemKlacc);
        Iterator<String> iterator = jsonObject.keys();
        while (iterator.hasNext()) {
          String key = iterator.next();
          if (flag) {
            map.put(key, jsonObject.opt(key));
          } else {
            Object obj = jsonObject.opt(key);
            if (obj instanceof JSONObject) {
              if (JSONObject.class.isAssignableFrom(itemKlacc)) {
                map.put(key, obj);
              } else {
                Object listItem = itemKlacc.newInstance();
                JSONObject jsonObjectNext = (JSONObject) obj;
                assignField(jsonObjectNext, itemKlacc, listItem);
                map.put(key, listItem);
              }
            } else if (obj instanceof JSONArray) {
              JSONArray jsonArrayNext = (JSONArray) obj;
              List nextList = createList(nextType, jsonArrayNext);
              map.put(key, nextList);
            }
          }
        }
        return map;
      }
    
      @SuppressWarnings("unchecked")
      private static List createList(Type type, JSONArray jsonArray) throws Exception {
        Class<?> klacc = getTclazz(type);
        boolean flag = isBaseType(klacc);
        int length = jsonArray.length();
        List list = new ArrayList<>();
        ParameterizedType parameterizedType = (ParameterizedType) type;
        Type nextType = parameterizedType.getActualTypeArguments()[0];
        Class<?> itemKlacc = getTclazz(nextType);
        for (int i = 0; i < length; i++) {
          if (flag) {
            list.add(jsonArray.get(i));
          } else {
            Object obj = jsonArray.get(i);
            if (obj instanceof JSONObject) {
              if (JSONObject.class.isAssignableFrom(itemKlacc)) {
                list.add(obj);
              } else {
                Object listItem = itemKlacc.newInstance();
                JSONObject jsonObject = (JSONObject) obj;
                assignField(jsonObject, itemKlacc, listItem);
                list.add(listItem);
              }
            } else if (obj instanceof JSONArray) {
              JSONArray jsonArrayNext = (JSONArray) obj;
              List nextList = createList(nextType, jsonArrayNext);
              list.add(nextList);
            }
          }
        }
        return list;
      }
    
      @SuppressWarnings("unchecked")
      private static Set createSet(Type type, JSONArray jsonArray) throws Exception {
        Class<?> klacc = getTclazz(type);
        boolean flag = isBaseType(klacc);
        int length = jsonArray.length();
        Set set = new HashSet();
        ParameterizedType parameterizedType = (ParameterizedType) type;
        Type nextType = parameterizedType.getActualTypeArguments()[0];
        Class<?> itemKlacc = getTclazz(nextType);
        for (int i = 0; i < length; i++) {
          if (flag) {
            set.add(jsonArray.get(i));
          } else {
            Object obj = jsonArray.get(i);
            if (obj instanceof JSONObject) {
              if (JSONObject.class.isAssignableFrom(itemKlacc)) {
                set.add(obj);
              } else {
                Object listItem = itemKlacc.newInstance();
                JSONObject jsonObject = (JSONObject) obj;
                assignField(jsonObject, itemKlacc, listItem);
                set.add(listItem);
              }
            } else if (obj instanceof JSONArray) {
              JSONArray jsonArrayNext = (JSONArray) obj;
              List nextList = createList(nextType, jsonArrayNext);
              set.add(nextList);
            }
          }
        }
        return set;
      }
    
      private static <T> void setterObject(Class<?> tClazz, String fieldName, Class<?> paramsClazz, T t, Object param) throws Exception {
        if (param instanceof Boolean && paramsClazz.isAssignableFrom(String.class)) {
          param = String.valueOf(param);
        }
        Method method = tClazz.getDeclaredMethod("set" + captureName(fieldName), paramsClazz);
        method.invoke(t, param);
      }
    }
    
    import java.lang.reflect.ParameterizedType;
    import java.lang.reflect.Type;
    
    /**
     * 指定反序列化的类型
     * TypeReference的存在是因为java中子类可以获取到父类泛型的真实类型
     */
    public abstract class TypeReference<T> {
      public Type genericParamType() {
        //获取父类类型
        //由于是抽象类,其实现类必然是继承当前类,所以父类类型即是TypeMarker<XXX>
        // getClass().getGenericSuperclass() 获取父类中的参数化类型(ParameterizedType)
        // getGenericSuperclass返回一个Type类型的对象,代表实体(class, interface, primitive type or void)的直接父类,
        // 如果父类是参数化类型,则返回的Type对象可准确反映源代码中使用的实际type参数。
        Type superType = getClass().getGenericSuperclass();
        //如果没有指定泛型参数,则返回的Type实际类型为Class
        //未指定泛型参数时,默认将泛型视为Object类
        if (superType instanceof Class) {
          return Object.class;
        }
        //如果有泛型参数,则返回的Type实际类型为ParameterizedType
        //强转并获取泛型参数,即XXX的实际类型
        // ParameterizedType是一个记录类型泛型的接口, 继承自Type, 一共三方法:
        // Type[] getActualTypeArguments(); //返回泛型类型数组
        // Type getRawType(); //返回原始类型Type
        // Type getOwnerType(); //返回 Type 对象,表示此类型是其成员之一的类型。
        ParameterizedType parameterizedType = (ParameterizedType) superType;
        // getActualTypeArguments:获取父类真实的泛型类型,返回泛型类型数组
        Type argumentType = parameterizedType.getActualTypeArguments()[0];
        return argumentType;
      }
    }
    

    相关文章

      网友评论

          本文标题:原生org.json实现JSON数据与对象之间的转化

          本文链接:https://www.haomeiwen.com/subject/nlxqkltx.html