利用FastJson,拼接復雜嵌套json數據&&直接從json字符串中(不依賴實體類)解析出鍵值對


 

1.拼接復雜嵌套json

FastJson工具包中有兩主要的類: JSONObject和JSONArray ,前者表示json對象,后者表示json數組。他們兩者都能添加Object類型的對象,但是JSONArray沒有put()方法,只有add()方法。這與json數組的定義有關,json數組只能添加元素,而不能添加鍵值對。而JSONObject因為是一個對象,不能容納其他對象,不能添加對象,沒有add() 方法,它就只有put()方法來添加鍵值對。JSONObject和JSONArray 似乎只能兩選一,要么用JSONObject的put()方法添加一個鍵值對,或使用JSONArray的add()方法添加一個元素。實際上是可以兩者兼顧的,JSONObect的put(String key,Object value)方法中值參數value是Object類型,那么這個數據類型也就可以是JSONArray類型。這樣的話,就可以在json對象中添加json數組中,從而輕松地拼接復雜的嵌套型的son數據。

如果要返回如下格式的json數據,常規的手工拼接將非常難以實現,且容易出錯。

 

 1).首先從最內層開始分析,最內層是兩個json對象,{item": "目錄管理","url": "/system/menu/toMain"},這個json對象有相應的實體類AdminMenu,而外層是一個json數組將這兩個對象包含進去。

        AdminMenu menu1 = new AdminMenu();
        menu1.setUrl("/system/menu/toMain");
        menu1.setName("目錄管理");//通過"getItem(){ return name}",所以只設置setName即可
        
        AdminMenu menu2 = new AdminMenu();
        menu2.setUrl("/system/user/toMain");
        menu2.setName("用戶管理");
        
        JSONArray level2Array = new JSONArray();
        //將兩個實體類添加一json數據中,FastJson會將實體類自動轉為json對象
        level2Array.add(menu1); 
        level2Array.add(menu2);

 

2).然后分析Level2(json數據)和Level1(鍵值對)又是一個匿名json對象的兩個屬性,把這兩個屬性添加到json對象中。

        JSONObject menuInfoElement = new JSONObject();
        menuInfoElement.put("Level2", level2Array);
        menuInfoElement.put("Level1", "系統管理");

 

3)再然后分析那個匿名json對象menuInfoElement是json數組menuInfo的唯一的一個元素,那么將匿名json對象menuInfoElement添加到menuInfo數組中。

        JSONArray menuInfoArray = new JSONArray();
        menuInfoArray.add(menuInfoElement);

 

4)再分析,menuInfo是json對象content的一個屬性

        JSONObject contentObj = new JSONObject();
        contentObj.put("menuInfo", menuInfoArray);

 

5)最終,將'status' 'content' 'message'作為最終返回的json對象的屬性

        JSONObject jsonMainObj = new JSONObject();
        jsonMainObj.put("status", "success");
        jsonMainObj.put("message", "查詢成功");
        jsonMainObj.put("content", contentObj);

 

測試代碼

  @Test
    public void testJson1()
    {
        AdminMenu menu1 = new AdminMenu();
        menu1.setUrl("/system/menu/toMain");
        menu1.setName("目錄管理");//通過"getItem(){ return name}",所以只設置setName即可
        
        AdminMenu menu2 = new AdminMenu();
        menu2.setUrl("/system/user/toMain");
        menu2.setName("用戶管理");
        
        JSONArray level2Array = new JSONArray();
        //將兩個實體類添加一json數據中,FastJson會將實體類自動轉為json對象
        level2Array.add(menu1); 
        level2Array.add(menu2);
        
        JSONObject menuInfoElement = new JSONObject();
        menuInfoElement.put("Level2", level2Array);
        menuInfoElement.put("Level1", "系統管理");
        
        JSONArray menuInfoArray = new JSONArray();
        menuInfoArray.add(menuInfoElement);
      
        
        JSONObject contentObj = new JSONObject();
        contentObj.put("menuInfo", menuInfoArray);
        
        JSONObject jsonMainObj = new JSONObject();
        jsonMainObj.put("status", "success");
        jsonMainObj.put("message", "查詢成功");
        jsonMainObj.put("content", contentObj);
        
        System.out.println(jsonMainObj.toJSONString());
    }

 

輸出的字符串

{"message":"查詢成功",
"content":{"menuInfo":[{"Level2":[{"item":"目錄管理","name":"目錄管理","url":"/system/menu/toMain"},
{"item":"用戶管理","name":"用戶管理","url":"/system/user/toMain"}],
"Level1":"系統管理"}]},
"status":"success"}

 

2.不依賴實體類,直接從json格式字符串中解析出鍵值對

JSONObject 有 parseObject(String text, Class<T> clazz) 靜態方法,將json字符串解析成T類型的java對象;而 JSONArray也有parseArray(String text, Class<T> clazz) 將json字符串解析成List<T>的集合對象。

但它們都需要傳入一個Class對象作為參數,換句話說,必須先有一個Class對應的實體類,而很多時候我們只會將其中的鍵值對解析出來用一次,只臨時使用它一次就去創建一個新的實體類,將會導致類爆炸。

 換種思路,JSONArray.parseArray(String text)將返回一個JSONArray對象。根據其add(Object obj)的方法入參類型是Object,那么其元素類型可能是一個實體類也可能是一個普通的json對象JSONObject,。但當前我們調用parseArray(String text)靜態方法傳入了的一個json字符串,以此構建出一個json數組,那么可以肯定其內部的元素類型一定是JSONObject,因此將其中的每個元素從Object強制轉換為JSONObject類型,然后再從每個JSONObject取出鍵值對。

 @Test
    public void parseJsonText()
    {
        String menuList = "[{'id':1,'locked':false,'loginedTime':'2014-01-21'},"
            + "{'id':2,'locked':true,'loginedTime':'2015-03-22'},]";
        /*
         * 有屬性名與之對應的User類,則可以寫成這種形式,但目前並不存在User類,
         * 所以無法實現 List<User> uList=JSONArray.parseArray(menuList, User.class);
         */
        JSONArray jUsers = JSONArray.parseArray(menuList);
        /**
         * 這個for循環也可以
         * for(int i=0;i<jUsers.size();i++){
            JSONObject user=jUsers.getJSONObject(i);
             }
         */
        for (Object userObj : jUsers)
        {
            JSONObject jUser = (JSONObject)userObj; // 強制類型轉換,因為知道其元素的具體類型是JSONObject,那么就不會出錯
            /**
             * {'id':1}鍵值對的值1沒加引號,FastJson認為它是數字,
             *  如果是{'id':'1'}格式,FastJson認為它是字符串,轉換為Integer將出錯
             */
            Integer id = (Integer)jUser.get("id");
            /*
             * {'locked':false}鍵值對的值沒加引號,FastJson視作boolean類型,
             * 如果是{'locked':'false'}格式,FastJson視作String類型,強制轉換為boolean將運行時出錯
             * 
             */
            boolean locked = (boolean)jUser.get("locked");
            String loginTime = (String)jUser.get("loginedTime");
            System.out.println("用戶id:" + id + " ,鎖定了嗎? " + locked + "  登錄時間:" + loginTime);
        }
    }

 

 

結果輸出

 

     另外需要注意,前端語言JavaScript是弱類型語言,它可以根據變量具體的值去推斷其類型,而JAVA是強類型語言,對字符串和數字有着明確的區分。

前端的{'id',23}和{'id','23'}沒有區別,但FastJson解析對這兩種格式有明顯的不同,前者鍵值對沒有引號的值(23)視為數字,后者鍵值對有引號的值('23')視作字符串。

    @Test
    public void parseJsonError()
    {
        String menuList = "[{'id':1,'locked':false,'loginedTime':'2014-01-21'},"
            + "{'id':2,'locked':true,'loginedTime':'2015-03-22'},]";
    
        JSONArray jUsers = JSONArray.parseArray(menuList);
        try{
            for (Object userObj : jUsers)
            {
                JSONObject jUser = (JSONObject)userObj; // 強制類型轉換,因為知道其元素的具體類型是JSONObject,那么就不會出錯
              
                String id = (String)jUser.get("id");//將出錯
              
                String locked = (String)jUser.get("locked");//將出錯
                String loginTime = (String)jUser.get("loginedTime");
                System.out.println("用戶id:" + id + " ,鎖定了嗎? " + locked + "  登錄時間:" + loginTime);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }

 

控制台提示類型轉換異常

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM