HungryForKnowledge HungryForKnowledge - 4 months ago 9
Java Question

Recursively parsing JSON via JSONObject to fetch value against specific keys

I have a complex JSON as below which I need to parser recursively. The end result of recursion is Map> type of object where key is the audience - name value and the inner map is Text-key, Title-value.
This is just a part of the complete 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"
}
}
}
}
}


I used JSONObject for this only to realise very late that iteration happens in reverse order :(

I tried to parse the whole structure recursively and reverse it to my benefit. BUt the order is going haywire :( :( mainly because of the text, title, snippet which follows the 2nd text,title and has 2 audience names. The text and title of that part get skipped due to which the whole order is compromised

Please help !! my current implementation is as below

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;
}

Answer

Found a solution to the ordering..ditched JSONObject API and used gson JsonObject instead

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;
}
Comments