2014-01-25 99 views
1

我有一個複雜的JSON,下面我需要遞歸解析。遞歸的最終結果是Map>對象的類型,其中key是受衆 - 名稱值,內部映射是Text-key,Title-value。 這只是完整JSON的一部分。通過JSONObject遞歸解析JSON以獲取特定鍵的值

"sections": { 
    "1": { 
    "1": { 
     "1": { 
     "title": "xxx", 
     "text": "xxx", 
     "tags": { 
      "audience": { 
      "1": { 
       "name": "xxx", 
       "title": "xxx", 
       "id": "xxx" 
      } 
      }, 
      "styleHint": { 
      "1": { 
       "name": "xxx", 
       "title": "xxx", 
       "id": "xxx" 
      } 
      } 
     } 
     }, 
     "title": "xxx", 
     "text": "xxx", 
     "tags": { 
     "audience": { 
      "1": { 
      "name": "xxx", 
      "title": "xxx", 
      "id": "xxx" 
      } 
     }, 
     "styleHint": { 
      "1": { 
      "name": "xxx", 
      "title": "xxx", 
      "id": "xxx" 
      } 
     } 
     } 
    }, 
    "2": { 
     "title": "xxx", 
     "text": "xxx", 
     "tags": { 
     "audience": { 
      "1": { 
      "name": "xxx", 
      "title": "xxx", 
      "id": "xxx" 
      } 
     }, 
     "styleHint": { 
      "1": { 
      "name": "xxx", 
      "title": "xxx", 
      "id": "xxx" 
      } 
     } 
     } 
    }, 
    "title": "xxx", 
    "text": "xxx", 
    "tags": { 
     "audience": { 
     "1": { 
      "name": "xxx", 
      "title": "xxx", 
      "id": "xxx" 
     }, 
     "2": { 
      "name": "xxx", 
      "title": "xxx", 
      "id": "xxx" 
     } 
     }, 
     "styleHint": { 
     "1": { 
      "name": "xxx", 
      "title": "xxx", 
      "id": "xxx" 
     } 
     } 
    } 
    }, 
    "2": { 
    "title": "xxx", 
    "text": "xxx", 
    "tags": { 
     "audience": { 
     "1": { 
      "name": "xxx", 
      "title": "xxx", 
      "id": "xxx" 
     } 
     }, 
     "styleHint": { 
     "1": { 
      "name": "xxx", 
      "title": "xxx", 
      "id": "xxx" 
     } 
     } 
    }, 
    "anchor":"xxx" 

    }, 
    "3": { 
    "1": { 
     "title": "xxx", 
     "text": "xxx", 
     "tags": { 
     "audience": { 
      "tag": { 
      "name": "xxx", 
      "title": "xxx", 
      "id": "xxx" 
      } 
     }, 
     "styleHint": { 
      "tag": { 
      "name": "xxx", 
      "title": "xxx", 
      "id": "xxx" 
      } 
     } 
     } 
    }, 
    "title": "xxx", 
    "text": "xxx", 
    "tags": { 
     "audience": { 
     "1": { 
      "name": "xxx", 
      "title": "xxx", 
      "id": "xxxx" 
     } 
     }, 
     "styleHint": { 
     "1": { 
      "name": "xx", 
      "title": "xxx", 
      "id": "xxxx" 
     } 
     } 
    } 
    } 
} 

我用的JSONObject這個才意識到已經很晚該迭代發生在相反的順序:(

我試圖遞歸解析整體的結構,它扭轉到我的利益,但爲了即將失控:(:(主要是因爲文本,標題,跟在第二個文本後面的片段,標題和2個觀衆名稱。該部分的文本和標題被跳過,因此整個訂單被盜用

請幫忙! !我目前的實施如下

private Map<String, Map<String, String>> parseTextAndTitle(JSONObject json, 
     Map<String, Map<String, String>> ttMap, String article, 
     List<String> usrGrp) throws JSONException { 
    logger.info("Entering method.."); 
    String userGroup = null; 
    Map<String, String> titleAndText = new LinkedHashMap<String, String>(); 
    Map<String, String> currMap = new LinkedHashMap<String, String>(); 
    Map<String, String> tempMap = new LinkedHashMap<String, String>(); 

    Iterator<String> keys = json.sortedKeys(); 

    while (keys.hasNext()) { 
     String key = keys.next(); 
     JSONObject value = null;String firstKey = null; 
     String text = null;String title = null; 
     int length = 0; 
     try { 
      value = json.getJSONObject(key); 
      if (key.equalsIgnoreCase(STYLEHINT) || key.equalsIgnoreCase(ANCHOR) 
        || key.equalsIgnoreCase(INLINE)) { 
       continue; 
      } 
      if (key.equals(TEXT)) { 
       text = json.getString(key); 
       text = removeHtmlTag(text); 
       logger.debug("TEXT RETRIEVED:" + text); 
       if(text != null) { 
        titleAndText.put(text, ""); 
       } 
       else 
        logger.debug("Text not retrieved!!"); 
      } 
      if (key.equals(TITLE)) { 
       title = json.getString(TITLE); 
       title = appendNewline(title); 
       logger.debug("TITLE RETRIEVED:" + title); 
       if (title != null) { 
        for (Map.Entry<String, String> iter : titleAndText 
          .entrySet()) 
         firstKey = iter.getKey(); 
        if(firstKey != null) { 
         titleAndText.put(firstKey, title); 
        } 
        else 
         logger.debug("NO key present in textAndTitle Map!!"); 
       } 
      } 
      if (key.equals(AUDIENCE_TAG)) { 
       try { 
        length = value.length(); 
        for (int i = 0; i < length; i++) { 
         userGroup = (String) value.getJSONObject(
           String.valueOf(i + 1)).get(NAME); 
         logger.debug("USERGROUP RETRIEVED:" + userGroup); 
         usrGrp.add(userGroup); 
        } 

       } catch (Exception e) { 
        userGroup = (String) value.getJSONObject(TAG).get(NAME); 
        logger.debug("USERGROUP RETRIEVED:" + userGroup); 
        usrGrp.add(userGroup); 
       } 
      } 
      else{ 
       parseTextAndTitle(value, ttMap, article, usrGrp); 
      } 
     } catch (Exception e) { 
      logger.debug("value not a JSON Object..rather an element"); 
      // Extract the text values 
      if (key.equals(TEXT)) { 
       text = json.getString(key); 
       text = removeHtmlTag(text); 
       logger.debug("TEXT RETRIEVED:" + text); 
       if(text != null) { 
        titleAndText.put(text, ""); 
       } 
       else 
        logger.debug("Text not retrieved!!"); 
      } 
      if (key.equals(TITLE)) { 
       title = json.getString(TITLE); 
       title = appendNewline(title); 
       logger.debug("TITLE RETRIEVED:" + title); 
       if (title != null) { 
        for (Map.Entry<String, String> iter : titleAndText 
          .entrySet()) 
         firstKey = iter.getKey(); 
        if(firstKey != null) { 
         titleAndText.put(firstKey, title); 
        } 
        else 
         logger.debug("NO key present in textAndTitle Map!!"); 
       } 
      } 
     } 
     if (!(usrGrp.isEmpty()) && !(titleAndText.isEmpty()) 
       && title != null) { 
      if(usrGrp.size() > 1) 
      { 
       for(int i=0;i<usrGrp.size();i++) 
       { 
        //If user group already present, extract current text,title map 
        //If not put usergroup as key, text,title map as value 
        if (ttMap.containsKey(usrGrp.get(i))) { 
         currMap = ttMap.get(usrGrp.get(i)); 
         if (currMap.isEmpty()) { 
          ttMap.put(usrGrp.get(i), titleAndText); 

         } else { 
          currMap = ttMap.get(usrGrp.get(i)); 
          for (Map.Entry<String, String> entry : currMap 
            .entrySet()) { 
           tempMap.put(entry.getKey(), 
             (String) entry.getValue()); 
          } 
          for (Map.Entry<String, String> ttEntry : titleAndText 
            .entrySet()) { 
           tempMap.put(ttEntry.getKey(), 
             (String) ttEntry.getValue()); 
          } 
          ttMap.put(usrGrp.get(i),tempMap); 
          //       titleAndText = new LinkedHashMap<String, String>(); 
          tempMap = new LinkedHashMap<String, String>(); 
         } 
        }      
        else { 
         ttMap.put(usrGrp.get(i), titleAndText); 
        } 
       } 
       titleAndText.clear(); 

      } 
      else 
      { 
       if (ttMap.isEmpty()) 
       { 
        tempMap = titleAndText; 
        ttMap.put(usrGrp.get(0), tempMap); 
       } 
       else { 
        currMap = ttMap.get(usrGrp.get(0)); 
        if (currMap.isEmpty()) { 
         ttMap.put(usrGrp.get(0), titleAndText); 
        }else { 
         currMap = ttMap.get(usrGrp.get(0)); 
         for (Map.Entry<String, String> entry : currMap 
           .entrySet()) { 
          tempMap.put(entry.getKey(), 
            (String) entry.getValue()); 
         } 
         for (Map.Entry<String, String> ttEntry : titleAndText 
           .entrySet()) { 
          tempMap.put(ttEntry.getKey(), 
            (String) ttEntry.getValue()); 
         } 
         ttMap.put(usrGrp.get(0),tempMap); 
         titleAndText.clear(); 

        } 
       } 

      } 
      usrGrp.clear(); 


     } 

    } 

    logger.info("Exiting method.."); 
    return ttMap; 
} 
+0

爲什麼使用你需要遞歸解析它?這裏沒有「嵌入JSON」,所以它是一個相對簡單的「對象」/地圖(我可以看到沒有數組/列表)。除了由數字鍵控的地圖(有點傻 - 爲什麼不使用數組),不需要遍歷鍵 - 可以簡單地通過鍵提取每個值。 –

+0

遞歸是需要的,因爲返回對象用於將值放入POJO中。這些值反過來用於以某種方式生成XML ..部分任務需求...我知道編號映射是愚蠢的..但是需要處理它們:(..加上需要文本,標題映射到觀衆..在XML中,根據受衆名稱,文本和標題放在不同的標籤.. – HungryForKnowledge

+0

您可能需要遞歸處理解析的JSON,但不需要遞歸解析,也不需要使用異常處理程序 - 您可以「獲取」對象並檢查其類型以避免異常(並且,無論如何,您絕對不應該捕捉到「異常」特別是如果你只是假設它是一個'JSONException'並且「吞下」它,當它可能是別的東西的時候。) –

回答

0

找到了解決的ordering..ditched的JSONObject API和GSON的JSONObject代替

private Map<String, List<String>> parseJsonSection(
     Map<String, List<String>> retTextMap, JsonObject jsonObject, 
     String lastKey, StringBuffer tt, List<String> ttext) 
       throws ParseException, JSONException { 

    for (Entry<String, JsonElement> entry : jsonObject.entrySet()) { 
     String key = entry.getKey(); 
     Object value = entry.getValue(); 
     logger.debug("Key:" + key + "\n" + value.toString()); 

     if (key.equalsIgnoreCase(STYLEHINT) || key.equalsIgnoreCase(INLINE) 
       || key.equalsIgnoreCase(ANCHOR)) 
      continue; 
     if (key.equalsIgnoreCase(TEXT)) { 
      tt.append(value.toString()); 
      ttext.add(tt.toString()); 
     } 
     if (key.equalsIgnoreCase(TITLE) && tt.length() == 0) { 
      tt = new StringBuffer(); 
      tt.append(value.toString() + "-"); 
     } 
     if (key.equalsIgnoreCase(NAME)) { 
      logger.debug("Value of usergrp:" + value.toString()); 
      String usrGrp = value.toString(); 
      if (retTextMap.isEmpty()) { 
       if (tt.toString() != null) { 
        List<String> temp = new ArrayList<String>(); 
        temp = ttext; 
        retTextMap.put(usrGrp, temp); 
       } 
       return retTextMap; 
      } else if (retTextMap.get(usrGrp) != null) { 
       List<String> temp = retTextMap.get(value.toString()); 
       if (!temp.contains(tt.toString())) 
        temp.add(tt.toString()); 
       retTextMap.put(usrGrp, temp); 
      } else if (retTextMap.get(usrGrp) == null) { 
       if (tt != null) { 
        List<String> temp = new ArrayList<String>(); 
        temp.add(tt.toString()); 
        retTextMap.put(usrGrp, temp); 
        return retTextMap; 
       } 
      } 
     } 
     if (value instanceof JsonObject) { 
      parseJsonSection(retTextMap, (JsonObject) value, key, tt, ttext); 
     } 
    } 
    return retTextMap; 
} 
0

而不是

while (keys.hasNext()) { 
    <blah blah> 
     if (key.equalsIgnoreCase(STYLEHINT) || key.equalsIgnoreCase(ANCHOR) 
       || key.equalsIgnoreCase(INLINE)) { 
      continue; 
     } 
     if (key.equals(TEXT)) { 
      <blah blah> 
     } 
     if (key.equals(TITLE)) { 
     .... 

人們可以簡單代碼:

text = json.getString(TEXT); 
<deal with text> 
title = json.getString(TITLE); 
<etc> 

如果有可能的是,一些關鍵值是不存在,獲取他們之前只是測試其不存在與has

由於STYLEHINT,ANCHOR和INLINE被忽略,因此不要取它們。

要處理JSON的扭曲佈局,這樣做:

if (json.has("title")) { 
    <extract title/text/tags/stylehint as described above> 
} 
else { 
    Iterator<String> keys = json.sortedKeys(); 
    while (keys.hasNext()) { 
     // Note that "key" must be "1", "2", "3"... 
     String key = keys.next(); 
     value = json.getJSONObject(key); 
     <recursively call method using "value"> 
    } 
} 
+0

它的遞歸..我通過keys迭代..如果它是一個獨立的或單一的循環...我可以做與has ..但我怎麼把它在這裏 – HungryForKnowledge

+0

@HungryForKnowledge - 不需要遍歷鍵。而且,因爲你總是使用'getJSONObject',你會得到所有字符串值的異常。既然你知道TEXT總是一個字符串,那麼對其執行'getJSONObject'就會很愚蠢,並且只要執行'getString'就會發生異常。 –

+0

和你如何計劃處理遞歸,如果你繼續做getString?整個觀點是通過一個對象遞歸。當一個getObject拋出異常...意味着它是一個String ..這是當我做一個getString .. – HungryForKnowledge

1
package Test.json; 

import java.util.Iterator; 

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

public class App { 
    public static void main(String[] args) { 
     String str = "{\"a\":\"1\", \"b\":\"2\", \"c\":[{\"d\":\"4\"},{\"e\":\"5\"},{\"f\":[{\"g\":\"6\"},{\"h\":\"7\"}]}], \"i\":8}"; 
     try { 
      loopThroughJson(new JSONObject(str)); 
     } catch (JSONException e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void loopThroughJson(Object input) throws JSONException { 
     if (input instanceof JSONObject) { 
      Iterator<?> keys = ((JSONObject) input).keys(); 
      while (keys.hasNext()) { 
       String key = (String) keys.next(); 
       if (!(((JSONObject) input).get(key) instanceof JSONArray)) 
        System.out.println(key + "=" + ((JSONObject) input).get(key)); 
       else 
        loopThroughJson(new JSONArray(((JSONObject) input).get(key).toString())); 
      } 
     } 
     if (input instanceof JSONArray) { 
      for (int i = 0; i < ((JSONArray) input).length(); i++) { 
       JSONObject a = ((JSONArray) input).getJSONObject(i); 
       Object key = a.keys().next().toString(); 
       if (!(a.opt(key.toString()) instanceof JSONArray)) 
        System.out.println(key + "=" + a.opt(key.toString())); 
       else 
        loopThroughJson(a.opt(key.toString())); 
      } 
     } 

    } 
} 



Output: 
a=1 
b=2 
d=4 
e=5 
g=6 
h=7 
i=8 
+0

你能詳細解釋一下嗎? – Ares

+1

有一個JSONObject和JSONArray的樹,這個算法遍歷所有鍵和所有值並將它們打印出來 – sklimkovitch

+0

將其編輯到問題中,並解釋它如何回答用戶的問題 – Ares