基于原生org.json.JSONObject和反射Reflect实现的JSON转换解析的工具类!

背景:业务需要,不可以用第三方json解析的开源项目,然后项目中又有很多接口都需要用到把字符串解析为对象的功能。

于是只能自己用原生的写一个了。吐槽(业务需要)。。。

致谢:

Android框架之路——Json解析一篇就够(原生技术+Gson+FastJson)

利用Java反射机制实现对象与json字符串互相转化

getDeclaredFields()-Reflection反射-获取包括父类在内的所有字段

通过java反射机制获取该类的所有属性类型、值、

正文:

import android.util.Log;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

public class JsonUtils {
    private static final String TAG = JsonUtils.class.getSimpleName();

    /**
     * 解析json字符串到实例对象
     *
     * @param clazz 和JSON对应的类的Class,必须拥有setXxx()函数,其中xxx为属性
     * @param json  被解析的JSON字符串
     * @return 返回传入的Object对象实例
     */
    public static <T> T parseJson2Object(String json, Class<T> clazz) {
        JSONObject jsonObject = null;
        try {
            jsonObject = new JSONObject(json);
        } catch (JSONException e) {
            FSLogcat.e(TAG, "Exception:" + e.getMessage());
            return null;
        }
        return parseJson2Object(clazz, jsonObject);
    }

    /**
     * 解析JSONObject对象到具体类,递归算法
     *
     * @param clazz      和JSON对应的类的Class,必须拥有setXxx()函数,其中xxx为属性
     * @param jsonObject 被解析的JSON对象
     * @return 返回传入的Object对象实例
     */
    private static <T> T parseJson2Object(Class<T> clazz, JSONObject jsonObject) {
        T obj = null;
        try {
            //获取clazz的实例
            obj = clazz.newInstance();
            Class tempClass = clazz;
            List<Field> fieldList = new ArrayList<>();
            while (tempClass != null && !tempClass.getName().toLowerCase().equals("java.lang.object")) {//当父类为null的时候说明到达了最上层的父类(Object类).
                fieldList.addAll(Arrays.asList(tempClass.getDeclaredFields()));
                tempClass = tempClass.getSuperclass(); //得到父类,然后赋给自己
            }
//            Collections.reverse(fieldList);
            // 遍历每个属性,如果为基本类型和String则直接赋值,如果为List则得到每个Item添加后再赋值,如果是其它类则得到类的实例后赋值
            for (Field field : fieldList) {
                try {
                    // 设置属性可操作
                    field.setAccessible(true);
//                    if (field.getName().equals("serialVersionUID")) {
//                        continue;
//                    }
                    FSLogcat.e(TAG, " GenericType = " + field.getGenericType().toString());
                    // 获取字段类型
                    Class<?> typeClazz = field.getType();
                    // 是否基础变量 Boolean,Character,Byte,Short,Integer,Long,Float,Double,Void
                    if (typeClazz.isPrimitive()) {
                        if (field.getGenericType().toString().equals("float")) {
                            Object opt = jsonObject.opt(field.getName());
                            if (opt instanceof Double) {
                                setProperty(obj, field, ((Double) opt).floatValue());
                            } else {
                                setProperty(obj, field, jsonObject.opt(field.getName()));
                            }
                        } else {
                            setProperty(obj, field, jsonObject.opt(field.getName()));
                        }
                    } else {
                        // 得到类型实例
                        Object typeObj;
                        if (typeClazz.isInterface() && typeClazz.getSimpleName().contains("List")) {//Field如果声明为List<T>接口,由于接口的Class对象不能newInstance(),此时需要转化为ArrayList
                            typeObj = ArrayList.class.newInstance();
                        } else {
                            typeObj = typeClazz.newInstance();
                        }
                        if (field.getName().equals("testMap")) {
                            Log.e(TAG, " pause");
                        }
                        if (typeObj instanceof Map) {// 是否为Map
                            try {
                                // 得到Map的JSONObject
                                JSONObject object = jsonObject.getJSONObject(field.getName());
                                // 得到类型的结构,如:java.util.HashMap<com.xxx.xxx>
                                Type type = field.getGenericType();
                                ParameterizedType pt = (ParameterizedType) type;
                                // 获得Map元素键类型
//                              Class<?> keyClass = (Class<?>) pt.getActualTypeArguments()[0];
                                // 获得Map元素值类型
                                Class<?> valueClass = (Class<?>) pt.getActualTypeArguments()[1];
                                JSONArray names = object.names();
                                for (int i = 0; i < names.length(); i++) {
                                    try {
                                        // 默认按map值为String进行解析
                                        String key = names.opt(i).toString();
                                        Object value = parseJson2Object(valueClass, object.getJSONObject(key));
                                        ((Map<String, Object>) typeObj).put(key, value);
                                    } catch (Exception e) {
                                        FSLogcat.e(TAG, "Exception:" + e.getMessage());
                                    }
                                }
                                setProperty(obj, field, typeObj);
                            } catch (Exception e) {
                                FSLogcat.e(TAG, "Exception:" + e.getMessage());
                            }
                        } else if (typeObj instanceof List) {// 是否为List
                            // 得到类型的结构,如:java.util.ArrayList<com.xxx.xxx>
                            Type type = field.getGenericType();
                            ParameterizedType pt = (ParameterizedType) type;
                            // 获得List元素类型
                            Class<?> dataClass = (Class<?>) pt.getActualTypeArguments()[0];
                            // 得到List的JSONArray数组
                            JSONArray jArray = jsonObject.getJSONArray(field.getName());
                            // 将每个元素的实例类加入到类型的实例中
                            for (int i = 0; i < jArray.length(); i++) {
                                //对于数组,递归调用解析子元素
                                try {
                                    ((List<Object>) typeObj).add(parseJson2Object(dataClass, jsonObject.getJSONArray(field.getName()).getJSONObject(i)));
                                } catch (JSONException e) {
                                    FSLogcat.e(TAG, "Exception:" + e.getMessage());
                                }
                            }
                            setProperty(obj, field, typeObj);
                        } else if (typeObj instanceof String) {// 是否为String
                            setProperty(obj, field, jsonObject.opt(field.getName()));
                        } else {//是否为其它对象
                            //递归解析对象
                            try {
                                setProperty(obj, field, parseJson2Object(typeClazz, jsonObject.getJSONObject(field.getName())));
                            } catch (JSONException e) {
                                FSLogcat.e(TAG, "Exception:" + e.getMessage());
                            }
                        }
                    }
                } catch (JSONException e) {
                    FSLogcat.e(TAG, "Exception:" + e.getMessage());
                } catch (IllegalAccessException e) {
                    FSLogcat.e(TAG, "Exception:" + e.getMessage());
                } catch (InstantiationException e) {
                    FSLogcat.e(TAG, "Exception:" + e.getMessage());
                }
            }
        } catch (IllegalAccessException e) {
            FSLogcat.e(TAG, "Exception:" + e.getMessage());
        } catch (InstantiationException e) {
            FSLogcat.e(TAG, "Exception:" + e.getMessage());
        }
        return obj;
    }

    /**
     * 给实例对象的成员变量赋值
     *
     * @param obj      实例对象
     * @param field    要被赋值的成员变量
     * @param valueObj 要被赋值的成员变量的值
     */
    private static void setProperty(Object obj, Field field, Object valueObj) {
        if (valueObj == null) {
            return;
        }
//        // 兼容类继承情况的判断
        Class<?> tempClass = obj.getClass();
        while (tempClass != null && !tempClass.getName().toLowerCase().equals("java.lang.object")) {//当父类为null的时候说明到达了最上层的父类(Object类).
            try {
                Method method = tempClass.getDeclaredMethod("set" + field.getName().substring(0, 1).toUpperCase(Locale.getDefault()) + field.getName().substring(1), field.getType());
                //设置set方法可访问
                method.setAccessible(true);
                //调用set方法为实例对象的成员变量赋值
                method.invoke(obj, valueObj);
                break; // 退出循环
            } catch (NoSuchMethodException e) {
                FSLogcat.e(TAG, "method [set" + field.getName().substring(0, 1).toUpperCase(Locale.getDefault()) + field.getName().substring(1) + "] not found");
                tempClass = tempClass.getSuperclass(); //得到父类,然后赋给自己
            } catch (IllegalArgumentException e) {
                FSLogcat.e(TAG, "method [set" + field.getName().substring(0, 1).toUpperCase(Locale.getDefault()) + field.getName().substring(1) + "] illegal argument:" + valueObj + "," + e.getMessage());
                break; // 退出循环
            } catch (IllegalAccessException e) {
                FSLogcat.e(TAG, "IllegalAccessException:" + e.getMessage());
                break; // 退出循环
            } catch (InvocationTargetException e) {
                FSLogcat.e(TAG, "IllegalAccessException:" + e.getMessage());
                break; // 退出循环
            } catch (Exception e) {
                FSLogcat.e(TAG, "Exception:" + e.getMessage());
                break; // 退出循环
            }
        }
        // 未兼容类继承后对父类私有方法的获取
//        try {
//            Class<?> clazz = obj.getClass();
//            //获取类的setXxx方法,xxx为属性
//            // getMethods(),该方法是获取本类以及父类或者父接口中所有的公共方法(public修饰符修饰的)
//            Method method = clazz.getMethod("set" + field.getName().substring(0, 1).toUpperCase(Locale.getDefault()) + field.getName().substring(1), field.getType());
//            // getDeclaredMethods(),该方法是获取本类中的所有方法,包括私有的(private、protected、默认以及public)的方法。
            Method method = clazz.getDeclaredMethod("set" + field.getName().substring(0, 1).toUpperCase(Locale.getDefault()) + field.getName().substring(1), field.getType());
//            //设置set方法可访问
//            method.setAccessible(true);
//            //调用set方法为实例对象的成员变量赋值
//            method.invoke(obj, valueObj);
//        } catch (NoSuchMethodException e) {
//            FSLogcat.e(TAG, "method [set" + field.getName().substring(0, 1).toUpperCase(Locale.getDefault()) + field.getName().substring(1) + "] not found");
//        } catch (IllegalArgumentException e) {
//            FSLogcat.e(TAG, "method [set" + field.getName().substring(0, 1).toUpperCase(Locale.getDefault()) + field.getName().substring(1) + "] illegal argument:" + valueObj + "," + e.getMessage());
//        } catch (IllegalAccessException e) {
//            FSLogcat.e(TAG, "IllegalAccessException:" + e.getMessage());
//        } catch (InvocationTargetException e) {
//            FSLogcat.e(TAG, "IllegalAccessException:" + e.getMessage());
//        }
    }

    /**
     * 可以解析自定义的对象、map、List、数组、基本数据类型、String
     *
     * @param value
     * @return
     */
    public static String object2JsonString(Object value) {
        if (value == null) {
            return "null";
        }
        if (value instanceof Boolean) {
            return value.toString();
        }
        if (value instanceof String) {
            return "\"" + escape((String) value) + "\"";
        }
        if (value instanceof Double) {
            if (((Double) value).isInfinite() || ((Double) value).isNaN()) {
//                return "null";
                return "0";
            } else {
                return value.toString();
            }
        }
        if (value instanceof Float) {
            if (((Float) value).isInfinite() || ((Float) value).isNaN()) {
//                return "null";
                return "0";
            } else {
                return value.toString();
            }
        }
        if (value instanceof Number) {
            return value.toString();
        }
        if (value instanceof Map) {
            return map2Json((Map) value);
        }
        if (value instanceof Collection) {
            return coll2Json((Collection) value);
        }
        if (value.getClass().isArray()) {
            return array2Json(value);
        }
        return customObject2Json(value);
    }

    private static String array2Json(Object array) {
        if (null == array) {
            return "null";
        }
        StringBuffer sb = new StringBuffer();
        sb.append('[');
        // 此处减1是为了下面的 逗号 追加
        int len = Array.getLength(array) - 1;
        if (len > -1) {
            int i;
            for (i = 0; i < len; i++) {
                sb.append(object2JsonString(Array.get(array, i))).append(",");
            }
            sb.append(object2JsonString(Array.get(array, i)));
        }
        sb.append(']');
        return sb.toString();
    }

    private static String coll2Json(Collection coll) {
        if (null == coll) {
            return "null";
        }
        StringBuffer sb = new StringBuffer();
        sb.append('[');
        for (Iterator it = coll.iterator(); it.hasNext(); ) {
            sb.append(object2JsonString(it.next()));
            if (it.hasNext()) {
                sb.append(",");
            }
        }
        sb.append(']');
        return sb.toString();
    }

    private static String customObject2Json(Object obj) {
        Class tempClass = obj.getClass();
        List<Field> fieldList = new ArrayList<>();
        while (tempClass != null && !tempClass.getName().toLowerCase().equals("java.lang.object")) {//当父类为null的时候说明到达了最上层的父类(Object类).
            fieldList.addAll(Arrays.asList(tempClass.getDeclaredFields()));
            tempClass = tempClass.getSuperclass(); //得到父类,然后赋给自己
        }
        Map map = new HashMap();
        for (Field f : fieldList) {
            if (Modifier.isStatic(f.getModifiers())) {
                continue;
            }
            String name = f.getName();
            f.setAccessible(true);
            Object value = null;
            try {
                value = f.get(obj);
            } catch (IllegalAccessException e) {
                value = null;
                FSLogcat.e(TAG, "Exception:" + e.getMessage());
            }
            map.put(name, value);
        }
        tempClass = null;
        fieldList = null;
        return map2Json(map);
//        Class type = obj.getClass();
//        Field[] fields = type.getDeclaredFields();
//        Map map = new HashMap();
//        for (Field f : fields) {
//            if (Modifier.isStatic(f.getModifiers())) {
//                continue;
//            }
//            String name = f.getName();
//            f.setAccessible(true);
//            Object value = null;
//            try {
//                value = f.get(obj);
//            } catch (IllegalAccessException e) {
//                value = null;
//                FSLogcat.e(TAG, "Exception:" + e.getMessage());
//            }
//            map.put(name, value);
//        }
//        type = null;
//        fields = null;
//        return map2Json(map);
    }

    private static String map2Json(Map map) {
        if (null == map) {
            return "null";
        }
        StringBuffer sb = new StringBuffer();
        sb.append('{');
        for (Iterator it = map.entrySet().iterator(); it.hasNext(); ) {
            Map.Entry entry = (Map.Entry) it.next();
            String key = (String) entry.getKey();
            if (null == key) {
                continue;
            }
            sb.append('\"');
            escape(key, sb);
            sb.append('\"').append(':').append(object2JsonString(entry.getValue()));
            if (it.hasNext()) {
                sb.append(",");
            }
        }
        sb.append('}');
        return sb.toString();
    }

    /**
     * Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters (U+0000 through U+001F).
     *
     * @param s
     * @return
     */
    private static String escape(String s) {
        if (s == null) {
            return null;
        }
        StringBuffer sb = new StringBuffer();
        escape(s, sb);
        return sb.toString();
    }

    private static void escape(String s, StringBuffer sb) {
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            switch (ch) {
                case '"':
                    sb.append("\\\"");
                    break;
                case '\\':
                    sb.append("\\\\");
                    break;
                case '\b':
                    sb.append("\\b");
                    break;
                case '\f':
                    sb.append("\\f");
                    break;
                case '\n':
                    sb.append("\\n");
                    break;
                case '\r':
                    sb.append("\\r");
                    break;
                case '\t':
                    sb.append("\\t");
                    break;
//                case '/':
//                    sb.append("\\/");
//                    break;
                case '/':
                    sb.append("/");
                    break;
                default:
                    if ((ch >= '\u0000' && ch <= '\u001F') || (ch >= '\u007F' && ch <= '\u009F') || (ch >= '\u2000' && ch <= '\u20FF')) {
                        String ss = Integer.toHexString(ch);
                        sb.append("\\u");
                        for (int k = 0; k < 4 - ss.length(); k++) {
                            sb.append('0');
                        }
                        sb.append(ss.toUpperCase());
                    } else {
                        sb.append(ch);
                    }
            }
        }
    }
}

不足:目前在Map<K,V>结构的数据解析时,只支持Map<K,V>的key为String类型的数据。(PS:Map<K,V>其实是可以使用对象类型做Key的。)

很尴尬,因为原生的new JSONObject(json);时如果json字符串里边的Map<K,V>的key是对象会直接报异常。。。

目前没找到好的方法解决,但是也够用了,如果有找到办法的麻烦知会我一声,以共同进步!非常感谢!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值