[JSON]org.json包深解析JSON字符串并转化为javaBean

org.json包深解析JSON字符串并转化javaBean


前言

  在使用org.json.JSONObject解析json字符串并转化为JavaBean的时候,发现只能进行浅解析,如果JavaBean的属性中含有JavaBean、Map、List等属性时,JSONObject无法进行解析转化。

  在网上大量搜索,没有发现能够进行深解析的办法或公开代码

  因此,无奈之下自己动手写了一个深解析的方法,用于将JSON字符串完全解析并转化为JavaBean,主要是利用Java 反射原理实现。

  测试通过了JavaBean中包含Map、List、JavaBean、枚举类型等属性及这些属性的层层嵌套的情况,最终均成功完成深解析,获得完整属性填充的JavaBean对象。


  代码如下、欢迎自取;

  使用时通过调用jsonToBean方法,传入json字符串及需要转化的JavaBean类型即可。

    public static<T> T jsonToBean(String jsonStr, Class<T> javaBeanClazz) throws NoSuchMethodException, NoSuchFieldException, InstantiationException, IllegalAccessException, InvocationTargetException {
        return toJavaBean(new JSONObject(jsonStr), javaBeanClazz);
    }

	public static <T> T toJavaBean(JSONObject map, Class<T> javaBeanClazz)
            throws JSONException, InvocationTargetException, IllegalAccessException, NoSuchFieldException, InstantiationException, NoSuchMethodException {
        Method[] beanMethods = javaBeanClazz.getDeclaredMethods();
        String methodProfix = "set";
        T javaBean = null;

        try {
            //enum类型不进行实例化
            if(!Enum.class.isAssignableFrom(javaBeanClazz)) {
                javaBean = javaBeanClazz.newInstance();
            } else {
                //enum类型默认使用findByValue方法,特殊情况再特殊处理
                methodProfix = "findBy";
                //if(AdActionType.class.equals(javaBeanClazz)){
                //    methodProfix = "findBy";
                //}
            }
        } catch (Exception e){
            throw new JSONException("Can not create a instance of Class "
                    + javaBeanClazz.getName() + ".");
        }
        for (Method method : beanMethods) {
            if (method.getName().startsWith(methodProfix)) {
                String field = method.getName();
                field = field.substring(field.indexOf(methodProfix) + methodProfix.length());
                field = field.toLowerCase().charAt(0) + field.substring(1);
                Type declaredFieldType = javaBeanClazz.getDeclaredField(field).getGenericType();

                //部分方法同样以set开头,但不是默认set方法
                Class<?>[] parameterTypes = method.getParameterTypes();
                if(!(parameterTypes.length == 1 &&
                        (ParameterizedType.class.isAssignableFrom(declaredFieldType.getClass())
                                && ((ParameterizedType) declaredFieldType).getRawType().equals(parameterTypes[0]) ||
                                (parameterTypes[0] == declaredFieldType)))
                ){
                    continue;
                }

                Object fieldValue = null;
                try {
                    fieldValue = map.get(field);
                } catch (JSONException e){
                    //e.printStackTrace();
                    continue;
                }

                //enum类型
                if(Enum.class.isAssignableFrom(javaBeanClazz)){
                    javaBean =  (T) method.invoke(null, fieldValue);
                    break;
                }

                Object paddingField = getPaddingField(declaredFieldType, fieldValue);
                method.invoke(javaBean, paddingField);
            }
        }
        return javaBean;
    }


    private static <T> Object getPaddingField(Type declaredFieldType, Object fieldValue) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, NoSuchFieldException, InstantiationException {
        Object result = fieldValue;
        if(Class.class.isAssignableFrom(declaredFieldType.getClass())){

            if(fieldValue.getClass() == JSONObject.class) {
                result = toJavaBean((JSONObject) fieldValue, (Class) declaredFieldType);
            } else {
                if(!declaredFieldType.equals(fieldValue.getClass())) {
                    result = getBaseTypeField((Class) declaredFieldType, fieldValue.toString());
                }
            }
        } else if(ParameterizedType.class.isAssignableFrom(declaredFieldType.getClass())) {
            //具体集合/Map类型
            Class<?> rawType = (Class<?>) ((ParameterizedType) declaredFieldType).getRawType();

            if (Collection.class.isAssignableFrom(rawType)) {
                Type elementType = ((ParameterizedType) declaredFieldType).getActualTypeArguments()[0];
                Collection<Object> collection = null;

                if (List.class.isAssignableFrom(rawType)) {//List默认ArrayList
                    collection = new ArrayList<>();
                } else if (Set.class.isAssignableFrom(rawType)) {//Set默认HashSet
                    collection = new HashSet<>();
                }

                if(ParameterizedType.class.isAssignableFrom(elementType.getClass())){
                    //递归调用
                    for(Object element : (JSONArray)fieldValue){
                        collection.add(getPaddingField(elementType, element));
                    }
                } else if(Class.class.isAssignableFrom(elementType.getClass())){
                    Class elementClass = (Class) elementType;
                    boolean isBaseType = isBaseType((Class) elementType);
                    for(Object element : (JSONArray)fieldValue){
                        if(isBaseType){
                            collection.add(element);
                        } else {
                            collection.add(toJavaBean((JSONObject) element, elementClass));
                        }
                    }
                }
                result = collection;
                //Set默认使用HashSet
            } else if (Map.class.isAssignableFrom((Class) rawType)) {
                Type[] actualTypeArguments = ((ParameterizedType) declaredFieldType).getActualTypeArguments();
                Class keyClass = (Class) actualTypeArguments[0];

                Type valueType = actualTypeArguments[1];
                boolean isCollectionOrMap = ParameterizedType.class.isAssignableFrom(valueType.getClass());

                Class valueClass = !isCollectionOrMap ? (Class) actualTypeArguments[1] : null;

                boolean isBaseType = !isCollectionOrMap ? isBaseType(valueClass) : false;

                Map<Object, Object> resultMap = new HashMap<>();
                Iterator<String> iterator = ((JSONObject) fieldValue).keys();
                while (iterator.hasNext()) {
                    //默认key为普通类型
                    String keyStr = iterator.next();
                    Object key = getBaseTypeField(keyClass, keyStr);

                    Object value = ((JSONObject) fieldValue).get(keyStr);
                    if(isCollectionOrMap){
                        value = getPaddingField(valueType, value);
                    }else if (!isBaseType) {
                        value = toJavaBean((JSONObject) value, valueClass);
                    }
                    resultMap.put(key, value);
                }
                result = resultMap;
            }
        }
        return result;
    }

    //认为String+八大基础类型为true
    public static boolean isBaseType(Class clazz){
        return clazz.isPrimitive() || clazz.equals(String.class) || clazz.equals(Integer.class) ||
                clazz.equals(Long.class) || clazz.equals(Character.class) || clazz.equals(Double.class) ||
                clazz.equals(Float.class) || clazz.equals(Boolean.class) || clazz.equals(Byte.class) || clazz.equals(Short.class);
    }

    //将str转化为基础字段
    public static <T> T getBaseTypeField(Class<T> clazz, String str){
        Object result = null;
        if(String.class.equals(clazz)){
            result = (T) str;
        }
        else if (int.class.equals(clazz) || Integer.class.equals(clazz)) {
            result = Integer.parseInt(StringUtils.isBlank(str) ? "0" : str);
        } else if(long.class.equals(clazz) || Long.class.equals(clazz)){
            result = Long.parseLong(StringUtils.isBlank(str) ? "0" : str);
        } else if(double.class.equals(clazz) || Double.class.equals(clazz)){
            result = Double.parseDouble(StringUtils.isBlank(str) ? "0" : str);
        } else if(float.class.equals(clazz) || Float.class.equals(clazz)){
            result = Float.parseFloat(StringUtils.isBlank(str) ? "0" : str);
        } else if(short.class.equals(clazz) || Short.class.equals(clazz)){
            result = Short.parseShort(StringUtils.isBlank(str) ? "0" : str);
        } else if(byte.class.equals(clazz) || Byte.class.equals(clazz)){
            result = Byte.parseByte(StringUtils.isBlank(str) ? "0" : str);
        } else if(char.class.equals(clazz) || Character.class.equals(clazz)){
            result = Character.valueOf(StringUtils.isBlank(str) ? ' ' : str.charAt(0));
        } else if(boolean.class.equals(clazz) || Boolean.class.equals(clazz)){
            result = Boolean.parseBoolean(StringUtils.isBlank(str) ? "false" : str);
        }
        return (T) result;
    }

  注意:

  • 枚举类型获取值的方法名用的是findByValue方法获取,不同时请修改第17行。
  • JavaBean对象及嵌套对象中的属性需要声明set方法才会被解析并注入。

  有问题欢迎大佬指出!

  本文原创,转载请标明链接。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值