1. 程式人生 > >通過GSON解析複雜json資料(二)

通過GSON解析複雜json資料(二)

這裡我們依舊用上文中的 json 字串 , 由於轉換為 map 依舊需要 javaBean , 所有我們的實體物件也不發生改變
這裡我們需要活用 java 反射和型別對比實現需求

先看程式碼

package com.jacx.test.test01.jsonutil;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import
java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * @author 劉合炎 * @description json物件轉java物件 * 此方法使用方法較為駁雜,請結合例子參考 -- JSONTest */ public
class TestJsonUtil { /** * 獲得物件的屬性和集合中的屬性 * @param clazz * @return */ private static List<Field> findFiledsAttr(Class clazz){ Field[] fields = null; List fieldList = new ArrayList(); while(true){ if(clazz == null){ break
; } fields = clazz.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { fieldList.add(fields[i]); System.out.println("fields:" +fields[i]); Class fieldType = fields[i].getType(); //判斷是否為基本型別 if(fieldType.isPrimitive() || fieldType.toString().equals("class java.lang.String")){ continue; }else{ //是使用者想要的型別? //if(fieldType.isAssignableFrom(List.class)){ Type type = fields[i].getGenericType(); if(type == null){ continue; } if(type instanceof ParameterizedType){//如果是泛型引數的型別 ParameterizedType pt = (ParameterizedType) type; Class genericClass = (Class)pt.getActualTypeArguments()[0];//得到泛型的class物件 //System.out.println("genericClass:"+genericClass); //遞迴直到獲得所有屬性 findFiledsAttr(genericClass); } //} } } clazz = clazz.getSuperclass(); } return fieldList; } public static void main(String[] args) { List<Field> fields= findFiledsAttr(TestGsonUnSer.class); for (int i = 0; i < fields.size(); i++) { System.out.println(fields.get(i)); } } /** * 轉換操作 * @param obj 基本物件 * @param obj2 物件中的物件 * @param ignores 是否摒棄 * @return */ public static Map convertBean2Map(Object obj,String[] ignores){ Map map = new LinkedHashMap(); Class clazz = obj.getClass(); List<Field> fields = findFiledsAttr(clazz); Field field = null; List taskList = null; for (int i = 0; i < fields.size(); i++) { field = fields.get(i); boolean flag = false; if(ignores != null && ignores.length > 0){ flag = isExistOfIgnores(field.getName(), ignores); } if(!flag){ Object value = getProperty(obj, field.getName()); if(null != value/* && !StringUtils.EMPTY.equals(value.toString())*/){ //判斷是否為基本型別 if(field.getType().isPrimitive() || field.getType().toString().equals("class java.lang.String")){ //基本型別直接設值即可 map.put(field.getName(), getProperty(obj, field.getName())); }else if(field.getType().isAssignableFrom(List.class)){ PropertyDescriptor pd = getPropertyDescriptor(obj.getClass(), field.getName()); Method getMethod = pd.getReadMethod(); Object objValue = null; try { objValue = getMethod.invoke(obj, new Object[]{}); System.out.println("finalValue:"+objValue); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(objValue instanceof List<?>){ System.out.println("==========================="); taskList = (List)objValue; } System.out.println("pd.getReadMethod():"+pd.getReadMethod()); /*//獲取class型別中的propertyName屬性 PropertyDescriptor pd = getPropertyDescriptor(obj.getClass(), field.getName()); //從屬性描述器中獲取get方法 Method getMethod = pd.getReadMethod(); System.out.println("field.getClass():"+getMethod);*/ //遍歷巢狀物件中的元素 //System.out.println("obj2:"+obj2); ParameterizedType pt = (ParameterizedType) field.getGenericType(); Class genericClass = (Class)pt.getActualTypeArguments()[0];//得到泛型的class物件 /*if (obj2 instanceof List<?>){ taskList = (List)obj2; }*/ List<LinkedHashMap<String, Object>> sonMap = new ArrayList<LinkedHashMap<String, Object>>(); for (int j = 0; j < taskList.size(); j++) { List<Field> sonFields = findFiledsAttr(taskList.get(j).getClass()); LinkedHashMap<String,Object> son2Map = new LinkedHashMap<String, Object>(); for (int k = 0; k < sonFields.size(); k++) { System.out.println("sonFields.get(k).getName():"+sonFields.get(k).getName()); if(sonFields.get(k).getType().isPrimitive() || sonFields.get(k).getType().toString().equals("class java.lang.String")){ son2Map.put(sonFields.get(k).getName(), getProperty(taskList.get(j), sonFields.get(k).getName())); System.out.println("子物件中的資料:"+son2Map); }else{ //遞迴至基本型別或String convertBean2Map(getProperty(taskList.get(j), sonFields.get(k).getName())); } } sonMap.add(son2Map); map.put(field.getName(), sonMap); } }else{ PropertyDescriptor pd = getPropertyDescriptor(obj.getClass(), field.getName()); Method getMethod = pd.getReadMethod(); Object objValue2 = null; try { objValue2 = getMethod.invoke(obj, new Object[]{}); System.out.println("finalValue:"+objValue2); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } List<Field> sonFields = findFiledsAttr(objValue2.getClass()); Map<String,Object> sonMap = new LinkedHashMap<String, Object>(); for (int j = 0; j < sonFields.size(); j++) { if(sonFields.get(j).getType().isPrimitive() || sonFields.get(j).getType().toString().equals("class java.lang.String")){ System.out.println("sonFields.get(j).getName():"+sonFields.get(j).getName()); sonMap.put(sonFields.get(j).getName(), getProperty(objValue2, sonFields.get(j).getName())); System.out.println("子物件中的資料:"+sonMap); }else{ //遞迴至基本型別或String convertBean2Map(getProperty(objValue2, sonFields.get(j).getName())); } } map.put(field.getName(), sonMap); } } } } return map; } /** * 過載 * @param obj * @param obj2 * @return */ public static Map convertBean2Map(Object obj){ return convertBean2Map(obj,null); } public static Map convertBean2MapForIngoreserialVersionUID(Object obj) { return convertBean2Map(obj, new String[] { "serialVersionUID" }); } private static boolean isExistOfIgnores(String fieldName,String[] ignores){ boolean flag = false; for(String str : ignores){ if(str.equals(fieldName)){ flag = true; break; } } return flag; } /** * 通過set方法設值 * @param obj * @param propertyName * @param value */ @SuppressWarnings("unchecked") private static void setProperty(Object obj, String propertyName,Object value) { Class clazz = obj.getClass();// 獲取物件的型別 PropertyDescriptor pd = getPropertyDescriptor(clazz, propertyName);// 獲取 clazz型別中的propertyName的屬性描述器 Method setMethod = pd.getWriteMethod();// 從屬性描述器中獲取 set 方法 try { setMethod.invoke(obj, new Object[] {value});// 呼叫 set 方法將傳入的value值儲存屬性中去 } catch (Exception e) { e.printStackTrace(); } } /** * 通過get方法獲取物件屬性值對應的值 * @param obj * @param propertyName * @return */ private static Object getProperty(Object obj,String propertyName){ Class clazz = obj.getClass(); //獲取class型別中的propertyName屬性 PropertyDescriptor pd = getPropertyDescriptor(clazz, propertyName); //從屬性描述器中獲取get方法 Method getMethod = pd.getReadMethod(); Object value = null; try { //呼叫value方法將傳入的value值儲存至屬性中 value = getMethod.invoke(obj, new Object[]{}); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } return value; } /** * get和set方法取值 * @param clazz * @param propertyName * @return */ private static PropertyDescriptor getPropertyDescriptor(Class clazz,String propertyName){ StringBuffer sb = new StringBuffer();//儲存方法名稱 Method setMethod = null; Method getMethod = null; PropertyDescriptor pd = null; try { //根據欄位名獲取欄位 Field f = clazz.getDeclaredField(propertyName); if(f != null){ String methodEnd = propertyName.substring(0,1).toUpperCase() + propertyName.substring(1); //構建set方法 sb.append("set" + methodEnd); setMethod = clazz.getDeclaredMethod(sb.toString(), new Class[]{f.getType()}); //構建get方法 sb.delete(0, sb.length());//清空 sb.append("get"+methodEnd); getMethod = clazz.getDeclaredMethod(sb.toString(), new Class[]{}); System.out.println("getMethod:"+getMethod); pd = new PropertyDescriptor(propertyName, getMethod,setMethod); } } catch (NoSuchFieldException e) { System.out.println("實體物件中沒有此屬性==="+e.getMessage()); } catch (SecurityException e) { System.out.println("此方法為私有的或訪問許可權不足==="+e.getMessage()); } catch (NoSuchMethodException e) { System.out.println("實體物件中的屬性必須有get/set方法==="+e.getMessage()); } catch (IntrospectionException e) { e.printStackTrace(); } return pd; } }

可以看到 , 在此工具類中通過反射機制拿到所有的屬性和屬性型別 , 將基本資料型別+String和物件型別分開做不同操作 , 通過方法反射拼接get和set方法取值/設值
這裡重中之重依舊是分析 json 應該轉換為何種型別

public static void main(String[] args) {
        String str = "[{\"users\":[{\"name\":\"系統001\",\"code\":\"sys01\"},{\"name\":\"系統003\",\"code\":\"sys03\"}],\"travel_theme\":\"測試002\",\"travel_start_time\":\"2017-08-08 10:07\",\"travel_end_time\":\"2017-08-22 10:07\",\"process_start_time\":\"2017-08-07 10:09:06\",\"process_end_time\":\"2017-08-07 10:28:46\"},{\"users\":[{\"name\":\"系統002\",\"code\":\"sys002\"}],\"travel_theme\":\"測試004\",\"travel_start_time\":\"2017-08-07 10:11\",\"travel_end_time\":\"2017-08-08 10:11\",\"process_start_time\":\"2017-08-07 10:12:34\",\"process_end_time\":\"2017-08-07 10:28:51\"}]";

        Gson gson = new Gson();
        List<TestGsonUnSer> list = gson.fromJson(str, new TypeToken<List<TestGsonUnSer>>(){}.getType());
        System.out.println("list:"+list);
        System.out.println(list.get(0).getUsers().get(0).getName());

        List<Map<String, List<Map<String, Object>>>> maps = new ArrayList<>();
        LinkedHashMap<String,List<Map<String, Object>>> sonMap = new LinkedHashMap<>();
        for (int i = 0; i < list.size(); i++) {
            for (int j = 0; j <  list.get(i).getUsers().size(); j++) {
                sonMap =   (LinkedHashMap<String, List<Map<String, Object>>>) 
                //第一個引數為最外層 javaBean 類型別,第二個為 List,傳入引數的同時將資料全部帶入
                TestJsonUtil.convertBean2Map(list.get(i), list.get(i).getUsers());
                System.out.println("list.get(i).getUsers().get(0):"+list.get(i).getUsers().get(j));
                System.out.println("sonMap:"+sonMap);
                //maps.add(sonMap);
            }
            maps.add(sonMap);
        }
        System.out.println("maps:"+maps);
    }

最後 maps 輸出

maps:[{users=[{name=系統001, code=sys01}, {name=系統003, code=sys03}], travel_theme=測試002, travel_start_time=2017-08-08 10:07, travel_end_time=2017-08-22 10:07, process_start_time=2017-08-07 10:09:06, process_end_time=2017-08-07 10:28:46}, {users=[{name=系統002, code=sys002}], travel_theme=測試004, travel_start_time=2017-08-07 10:11, travel_end_time=2017-08-08 10:11, process_start_time=2017-08-07 10:12:34, process_end_time=2017-08-07 10:28:51}]

和我們想要的結果一致