1. 程式人生 > >[Android開發] Json解析工具類,一個類搞定Json的解析

[Android開發] Json解析工具類,一個類搞定Json的解析

一、簡介

利用遞迴的方式反射解析到bean裡面

二、詳細程式碼

1、 Json格式

例如伺服器指定規定json格式為:

{
    "code": "……" ,      // 返回代號,預留欄位,預設返回null
    "type":"ERROR",     // 返回型別,表示操作是成功或失敗
    "desc":"……",        // 返回描述,描述性文字,主要儲存用於彈窗顯示的文字
    "action":"SHOW",   //返回操作,該操作值提供給終端使用,用於決定當前收到返回後的操作
    "data": "……"        // 返回資料,根據請求上傳的引數,返回對應的資料,或返回null
}

對應的資料在data裡面,data裡面的key對應一個bean,例如一個列表資料:

{
    "desc":"查詢成功",
    "data":{
        "diseaseList":[
            {
                "xmlName":"精神病評估",
                "xmlId":"1066",
                "category":"symptom"
            },
            {
                "xmlName":"對學習困難和認知延遲的評估",
                "xmlId
":"884", "category":"symptom" }, { "xmlName":"疲乏的評估", "xmlId":"571", "category":"symptom" }, { "xmlName":"痴呆的評估", "xmlId":"242", "category":"symptom"
}, { "xmlName":"非故意性體重減輕評估", "xmlId":"548", "category":"symptom" } ]
}
, "action":null, "code":"", "type":"SUCCESS" }

2、定義資料Bean類

上面的list的bean定義為DiseaseList.java

public class DiseaseList  {


    /**
     * xmlName : 分裂情感性障礙
     * xmlId : 1199
     * category : disease
     */

    private String xmlName;     //症狀名字
    private String xmlId;       //症狀名字
    private String category;    //分類的 英文名

    private String letter = ""; //字母,轉為拼音後在這裡新增

    public String getXmlName() {
        return xmlName;
    }

    public void setXmlName(String xmlName) {
        this.xmlName = xmlName;
    }

    public String getXmlId() {
        return xmlId;
    }

    public void setXmlId(String xmlId) {
        this.xmlId = xmlId;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }


    public String getLetter() {
        return letter;
    }

    public void setLetter(String letter) {
        this.letter = letter;
    }
}

3、定義根key的bean類

Response.java:

/**
 * json返回的首key的內容類
 * 
 */
public class Response {

    //下面四個是固定寫在第一層的
    private String code;
    private String type;
    private String desc;
    private String action;


    //Object 可以存放list
    private HashMap<String,Object> datas = new HashMap<String,Object>();   //存放物件(一般是list),根據String這個id來取

    //存放data裡面的基本型別
    private HashMap<String,Object> dataValue = new HashMap<>();

    public Response() {

        code = type = desc = action /*= version = token = applyAuthenticateId*/ = "";

    }


    public final static String TOKEN = "token";
    public final static String VERSION = "version";
    public final static String PORTRAIT = "portrait";
    public final static String USERID = "userId";
    public final static String APPLYAUTHENTICATEID = "applyAuthenticateId";
    public final static String ISDOCTOR = "isDoctor";
    public final static String ISEXPERT = "isExpert";

    public final static String WAY = "way";
    public final static String DOWNLOAD = "download";



    /**
     * 存值到hashmap裡面
     * @param key
     * @param value
     */
    public void put(String key, Object value) {
        datas.put(key, value);
    }

    /**
     * 獲取key對應的物件
     * @param key key
     * @param <T> 返回的物件
     * @return  hashMap的key對應的值
     */
    public <T> T get(String key){

        if(datas.containsKey(key)){
            return (T)datas.get(key);
        }

        return null;
    }


    /**
     * 反射執行,新增到hashMap,data裡面的基本型別資料
     * @param key
     * @param value
     */
    public void addDataValue(String key, Object value){

        dataValue.put(key,value);
    }

    /**
     * 獲取data裡面的基本型別資料
     * @param key
     * @param <T>
     * @return
     */
    public <T> T getDataValue(String key){
        if(dataValue.containsKey(key)){
            return (T)dataValue.get(key);
        }

        return null;
    }



    public String getCode() {
        return code;
    }

    public void setCode(String code) {

        if(null != code && !"".equals(code.trim()))
            this.code = code;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        if(!TextUtils.isEmpty(desc))
            this.desc = desc;
    }


}

4、定義反射類列舉

json解析時候根據key在這裡獲取到對應的類例項
DATA.java:

/**
 * json解析的時候的類
 */
public enum DATA {

    //疾病列表
    DISEASELIST("diseaseList",DiseaseList.class)

    ;

    private final String mId;

    private final Class cls;

    public Class getClzss() {
        return cls;
    }

    DATA(String id, Class clzss) {
        mId = id;
        cls = clzss;
    }

    /**
     * 根據json的key獲取類
     * @param id
     * @return
     */
    public static DATA fromId(String id) {

        DATA[] values = values();
        int cc = values.length;

        for (int i = 0; i < cc; i++) {
            if (values[i].mId.equals(id)) {
                return values[i];
            }
        }

        return null;
    }

    @Override
    public String toString() {
        return mId;
    }
}

5、 Json解析工具類

對應的註釋已經寫到程式碼裡面了
JsonResolveUtils.java

/**
 * json解析工具類
 */
public class JsonResolveUtils {

    private static final String SET = "set";
    private static final String PUT = "put";

    /**
     * 開始解析json 字串,解析為Response類bean形式
     *
     * @param response json字串
     * @param cls      Response類class
     * @param <T>      泛型,這裡傳遞了Response
     * @return
     */
    public static <T> T parseJsonToResponse(String response, Class<T> cls) {

        if (null != response) {

            try {
                // 構建JSONObject 例項
                JSONObject json = new JSONObject(response);
                // JSONObject 解析成具體Bean例項
                T entity = toResponse(json, cls);

                return entity;

            } catch (JSONException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * JSONObject解析成Response Bean例項
     *
     * @param json json物件
     * @param cls  轉換的物件,這裡是Response
     * @param <T>  轉換的物件,這裡是Response
     * @return 返回Response物件
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static <T> T toResponse(JSONObject json, Class<T> cls) throws IllegalAccessException, InstantiationException {

        //宣告一個Response例項
        T instance = null;

        if (null != json) {
            // 獲取根key
            Iterator<String> iterator = json.keys();
            //構建個例項Response Bean
            instance = cls.newInstance();
            //開始遍歷根 key
            while (iterator.hasNext()) {

                try {
                    String key = iterator.next();  //獲取key
                    Object value = json.get(key);  //獲取key對應的值
                    //值不為空
                    if (null != value) {

                        if (!key.equals("data")) {
                            //不是data資料,直接為Response的Bean屬性賦值
                            setter(instance, key, value);

                        } else {  // 解析data資料

                            if (value instanceof JSONObject) {
                                //data 資料是JSONObject 開始解析json物件資料
                                parseJsonBean((JSONObject) value, instance);
                            } else if (value instanceof JSONArray) {
                                //data 資料是JSONArray 開始解析json陣列資料
                                toBeanArray((JSONArray) value, instance);
                            } else {
                                //若都不是,直接為ResponseBean屬性賦值
                                setter(instance, key, value);
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } // while(~)
        }
        return instance;
    }

    /**
     * 解析單個JSON資料
     *
     * @param json     json
     * @param instance Bean例項
     * @param <T>
     */
    public static <T> void parseJsonBean(JSONObject json, T instance) {
        //json不為空
        if (null != json) {
            //獲取json的key iterator
            Iterator<String> iterator = json.keys();

            while (iterator.hasNext()) {

                //獲取鍵值對
                String key = iterator.next();
                Object value = null;
                try {
                    //獲取值
                    value = json.get(key);
                    //value不為空
                    if (null != value) {
                        // value 為json物件 則把json解析成具體的例項Bean
                        if (value instanceof JSONObject) {

                            // 獲取對應的例項Bean Class
                            DATA clzss = DATA.fromId(key);
                            //不為空
                            if (null != clzss) {
                                //把json解析成該例項Bean
                                Object entity = toBean((JSONObject) value, clzss.getClzss());
                                //把當前Bean類快取在上級Bean屬性裡
                                putter(instance, entity.getClass(), key, entity);
                            }
                        } else if (value instanceof JSONArray) { //value 為json 資料物件,則把jsonarray解析成ArrayList<Bean>
                            // 獲取對應的例項Bean Class
                            DATA clzss = DATA.fromId(key);
                            if (null != clzss) {
                                //把json解析成ArrayList<Bean>
                                Object entity = parseBeanArray((JSONArray) value, clzss.getClzss());
                                //把當前ArrayList<Bean>快取在上級Bean屬性裡
                                putter(instance, entity.getClass(), key, entity);
                            }
                        } else {
                            //都是不是,直接為上級Bean屬性賦值
                            if (instance instanceof Response) {
                                //dada下面的標準型別的值設定進Respone的dataString
                                setDataString(instance,key, value.toString());
                            } else {
                                putter(instance, value.getClass(), key, value);
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 設定Response的dataString
     *
     * @param obj
     * @param key
     * @param value
     * @param <T>
     */
    private static  <T> void setDataString(Object obj, String key, String value) {
        //值不為空
        if (null == value)
            return;

        try {
            //獲取addDataString方法,引數1 為方法名,2為型別
            Method method = obj.getClass().getMethod("addDataValue", String.class, Object.class);
            //呼叫set方法賦值
            method.invoke(obj, key, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 解析JSON成具體例項Bean
     *
     * @param json json資料
     * @param cls  要解析成為的例項
     * @param <T>  返回例項
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static <T> T toBean(JSONObject json, Class<T> cls) throws IllegalAccessException, InstantiationException {
        //宣告例項引用
        T instance = null;
        //json不為空
        if (null != json) {
            //獲取json key 的迭代器;
            Iterator<String> iterator = json.keys();
            //構建例項Bean
            instance = cls.newInstance();
            //遍歷json key
            while (iterator.hasNext()) {
                //獲取鍵值對
                String key = iterator.next();
                Object value = null;
                try {
                    value = json.get(key);
                    //value不為空
                    if (null != value) {
                        // value 為json物件 則把json解析成具體的例項Bean
                        if (value instanceof JSONObject) {
                            // 獲取對應的例項Bean Class
                            DATA clzss = DATA.fromId(key);
                            if (null != clzss) {
                                //把json解析成該例項Bean
                                Object entity = toBean((JSONObject) value, clzss.getClzss());
                                //把當前Bean類快取在上級Bean屬性裡
                                putter(instance, entity.getClass(), key, entity);
                            }
                        } else if (value instanceof JSONArray) { //value 為json陣列物件,則把jsonarray解析成ArrayList<Bean>
                            // 獲取對應的例項Bean Class
                            DATA clzss = DATA.fromId(key);
                            if (null != clzss) {
                                //把json解析成ArrayList<Bean>
                                Object entity = parseBeanArray((JSONArray) value, clzss.getClzss());
                                //把當前ArrayList<Bean>快取在上級Bean屬性裡
                                putter(instance, entity.getClass(), key, entity);
                            }
                        } else {
                            //都是不是,直接為上級Bean屬性賦值
                            setter(instance, key, value);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return instance;
    }

    /**
     * 解析json裡面的json陣列,例如專家列表
     *
     * @param jsonarr
     * @param cls
     * @param <T>
     * @return
     */
    public static <T> ArrayList<Object> parseBeanArray(JSONArray jsonarr, Class<T> cls) {

        //宣告集合List引用
        ArrayList<Object> beanArray = null;
        //宣告例項引用
        T instance = null;  // if area

        if (null != jsonarr && jsonarr.length() > 0) {

            beanArray = new ArrayList<Object>();
            int count = jsonarr.length();
            Object value = null;
            for (int index = 0; index < count; index++) {

                try {
                    value = jsonarr.get(index);
                    if (value instanceof String) {
                        beanArray.add(value);
                        continue;
                    } else {
                        //構造例項Bean
                        instance = cls.newInstance();
                        // value 為json物件 則把json解析成具體的例項Bean
                        if (value instanceof JSONObject) {
                            parseJsonBean((JSONObject) value, instance);
                        } else if (value instanceof JSONArray) {
                            //value 為json 陣列物件,則解析jsonarray
                            toBeanArray((JSONArray) value, instance);
                        }
                        //解析完成後將Bean新增到List
                        beanArray.add(instance);
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return beanArray;
    }

    /**
     * 解析data的key 的json陣列
     *
     * @param jsonarr  json資料
     * @param instance Response例項
     * @param <T>
     * @return
     */
    public static <T> T toBeanArray(JSONArray jsonarr, T instance) {

        if (null != jsonarr && jsonarr.length() > 0) {
            int count = jsonarr.length();
            Object value = null;
            for (int index = 0; index < count; index++) {

                try {
                    value = jsonarr.get(index);
                    if (value instanceof JSONObject) {

                        parseJsonBean((JSONObject) value, instance);

                    } else if (value instanceof JSONArray) {

                        toBeanArray((JSONArray) value, instance);

                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }

            }
        }
        return instance;
    }

    /**
     * 呼叫obj類的get引數menber方法
     *
     * @param obj
     * @param member
     * @param <T>
     * @return
     */
    public static <T> T getter(Object obj, String member) {

        try {

            Method method = obj.getClass().getMethod("get" + updateFirst(member));
            return (T) method.invoke(obj);

        } catch (Exception e) {
            return null;
        }

    }

    /**
     * 反射的方法獲取
     *
     * @param obj
     * @param member
     * @param <T>
     * @return
     */
    public static <T> T getterIgnoreCase(Object obj, String member) {

        try {

            Method method = obj.getClass().getMethod("get" + member);
            return (T) method.invoke(obj);

        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 為obj例項的屬性賦值
     *
     * @param obj   目標例項
     * @param clzss set方法形參型別
     * @param value 屬性值
     */
    public static void putter(Object obj, Class<?> clzss, Object... value) {

        //值不為空
        if (null == value)
            return;

        try {
            //獲取key對應的set方法,引數1 為方法名,2為型別
            Method method = obj.getClass().getMethod(SET + updateFirst((String) value[0]), clzss);
            //呼叫set方法賦值
            method.invoke(obj, value[1]);

        } catch (Exception e) {
            //若obj沒有對應的set方法
            try {
                //獲取obj的put方法
                Method method = obj.getClass().getMethod(PUT, value[0].getClass(), Object.class);
                //把屬性值put入map裡快取
                method.invoke(obj, value);
                //System.out.println(obj.getClass()+ "呼叫"+value[0].toString()+" "+((ArrayList)value[1]).size());
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }

    }

    /**
     * 反射執行
     *
     * @param obj
     * @param member
     * @param value
     */
    public static void setter(Object obj, String member, Object value) {

        if (null == value)
            return;
        try {
            Method method = obj.getClass().getMethod(SET + updateFirst(member), value.getClass());
            method.invoke(obj, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 首字元大寫
     *
     * @param member
     * @return
     */
    public static String updateFirst(String member) {

        String first = member.substring(0, 1).toUpperCase();
        String suffex = member.substring(1, member.length());
        return new StringBuilder().append(first).append(suffex).toString();

    }

}

三、使用

例如第一個資料獲取到list資料

        //解析為response
        Response response = JsonResolveUtils.parseJsonToResponse(json,Response.class);

從response裡面獲取list資料
List<DiseaseList> list = new ArrayList<>();

//獲取完成開始解析為list bean
        Response response = JsonResolveUtils.parseJsonToResponse(json,Response.class);

        ArrayList cache = null;
        cache = response.get(DATA.DISEASELIST.toString());
        if(cache != null && !cache.isEmpty()){
            //新增到list
            list.addAll(cache);
            Log.e("tpnet",list.size()+"個數據");
        }else{
            //獲取資料失敗操作
        }

四、使用注意

解析的時候是根據返回的格式進行解析的,如果有數字型別的資料。在bean裡面應該寫完整幾種型別的數字,例如金額:

public class FinanceRecords {


    private String sum;       //金額

    public String getSum() {
        return sum;
    }

    //新增下面四種類型供json反射回調

    public void setSum(String sum) {
        this.sum = sum;
    }

    public void setSum(Integer sum) {
        this.sum = sum+"";
    }

    public void setSum(Float sum) {
        this.sum = sum+"";
    }

    public void setSum(Double sum) {
        this.sum = sum+"";
    }

}

下一篇文章有一個完整的demo。