Recursively parsing JSON via JSONObject to fetch value against specific keys - java

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

Modified #sklimkovitch code to get it working in some complex Json Structure...
public 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))
if (((JSONObject) input).get(key) instanceof JSONObject) {
loopThroughJson(((JSONObject) input).get(key));
} else
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);
loopThroughJson(a);
}
}
}

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

Instead of
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)) {
....
One can simply code:
text = json.getString(TEXT);
<deal with text>
title = json.getString(TITLE);
<etc>
If it's possible that the some of the key values are not there, simply test for their absence with has before fetching them.
Since STYLEHINT, ANCHOR, and INLINE are ignored, simply don't fetch them.
To handle the screwy layout of the JSON, do this:
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">
}
}

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

Related

Get data from nested JSON Object in Java Android

How I can get the "fields" objects 0,1,2,3,4 & only the "name" object string of every object using JSONOBJECT
[
{
"name": "Bank1",
"fields": {
"0": {
"name": "Email",
"slug": "email",
"type": "input"
},
"1": {
"name": "City",
"slug": "city",
"type": "input"
},
"2": {
"name": "Screenshot",
"slug": "screenshot",
"type": "file"
},
"3": {
"name": "Full Name",
"slug": "full-name",
"type": "input"
}
},
"status": "Active"
},
{
"name": "Bank2",
"fields": {
"0": {
"name": "Email",
"slug": "email",
"type": "input"
},
"1": {
"name": "City",
"slug": "city",
"type": "input"
},
"2": {
"name": "Screenshot",
"slug": "screenshot",
"type": "file"
},
"4": {
"name": "Submitted Date",
"slug": "submitted-date",
"type": "calendar"
}
},
"status": "Active"
}
]
& this is what I try to done
public void onResponse(String response) {
try {
JSONArray jsonArray = new JSONArray(response);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
String p_name = jsonObject.getString("name");
JSONObject jo = jsonObject.getJSONObject("fields");
String j1 = jo.getString("0");
if (!j1.isEmpty()){
JSONObject jo1 = jo.getJSONObject("0");
String f_name1 = jo1.getString("name");
Log.d("Field1.", f_name1);
}
}}catch block...
but the problem is, it gives me value of the object null like [value 4 is null] cuz there is no object for 4 in the first object of fields. please help me solve this prob, appreciate your answers thankyou :)
You can use keys() iterator of json object & loop on it using while (keys.hasNext())
For your example, it would look something like this:
private void parseJson(String response) {
try {
JSONArray jsonArray = new JSONArray(response);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
JSONObject jo = jsonObject.getJSONObject("fields");
Iterator<String> keys = jo.keys();
while (keys.hasNext()) {
String key = keys.next();
JSONObject jo1 = jo.getJSONObject(key);
String f_name1 = jo1.getString("name");
Log.d("Field1.", f_name1);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
There are some problems with get all keys properly in my IDE/JDK11, so I decided to loop over an ArrayList, basing on #MayurGajra solution, ex:
private static List<List<String>> parseJson(String response) throws JSONException {
JSONArray jsonArray = new JSONArray(response);
List<List<String>> result = new ArrayList<>();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
JSONObject jo = jsonObject.getJSONObject("fields");
List<Object> list = new ArrayList<>();
jo.keys().forEachRemaining(list::add);
List<String> subList = new ArrayList<>();
for (Object o : list) {
String key;
if (isString(o))
key = (String) o;
else
continue;
JSONObject jo1 = jo.getJSONObject(key);
String f_name1 = jo1.getString("name");
subList.add(f_name1);
}
result.add(subList);
}
return result;
}
private static boolean isString(Object o) {
try {
String result = (String) o;
} catch (ClassCastException e) {
return false;
}
return true;
}
The result obtained after processing the above json is as follows:
[[Email, City, Screenshot, Full Name], [Email, City, Screenshot, Submitted Date]]
but it have not to be a List of Lists ;)
-- edit --
To get only first list of elements labeled "name":
try {
System.out.println(parseJson(yourJsonAsString).get(0).toString());
} catch (JSONException e) {
System.out.println("JSONException:" + e.getMessage());
}
The result of above is:
[Email, City, Screenshot, Full Name]

How to add a new property to a Json object while iterating

I want to basically merge data from several json files into one final json file.
The following stripped down version of the code searches for a property, let's say 'label' and updates its value 'new_value'.
This works so far.
But what I need now, is a new property within the node, where the search succeeds.
So basically a new property under 'label' named 'label_new' with value to 'new_value'.
Here is a basic recursive implementation. I know that I need to replace somehow, but every attempt I tried did not work.
Any suggestion that may help?
-Thx
Java:
private static Object k = null;
private static Object v = null;
private static Object parent = null;
public static void iterate(Object obj, JSONObject props, String search) throws Exception {
try {
if (obj instanceof JSONObject) {
parent = obj;
for (Iterator it = ((JSONObject) obj).keys(); it.hasNext();) {
k = it.next();
v = ((JSONObject) obj).get((String) k);
iterate(v, props, search);
}
}
if (obj instanceof JSONArray) {
for (int i = 0; i < ((JSONArray) obj).length(); i++) {
v = ((JSONArray) obj).get(i);
iterate(v, props, search);
}
}
if (obj instanceof String) {
if (k.toString().equalsIgnoreCase(search)) {
((JSONObject) parent).put(search, "NEW_VALUE");
// ((JSONObject) parent).put(search + "_new", "NEW_VALUE");
}
}
} finally {
}
The starting json:
{
"data": {
"group": {
"subGroup": {
"boolean": {
"name": "test",
"description": "test",
"label": "new_value"
},
"description": "test",
"label": "test",
"text": {
"name": "test",
"description": "test",
"label": "new_value"
}
},
"name": "test",
"description": "test",
"label": "test"
}
}
}
The final output I need:
{
"data": {
"group": {
"subGroup": {
"boolean": {
"name": "test",
"description": "test",
"label": "new_value",
"label_new": "new_value"
},
"description": "test",
"label": "test",
"text": {
"name": "test",
"label": "new_value",
"label_new": "new_value"
}
},
"name": "test",
"description": "test",
"label": "new_value",
"label_new": "new_value"
}
}
}
UPDATE:
private static Object k = null;
private static Object v = null;
public static void iterate(Object obj, Object parent, JSONObject props, String search) throws Exception {
try {
if (obj instanceof JSONObject) {
for (Iterator it = ((JSONObject) obj).keys(); it.hasNext();) {
k = it.next();
v = ((JSONObject) obj).get((String) k);
iterate(v, obj, props, search);
}
}
if (obj instanceof JSONArray) {
for (int i = 0; i < ((JSONArray) obj).length(); i++) {
v = ((JSONArray) obj).get(i);
iterate(v, obj, props, search);
}
}
if (obj instanceof String) {
if (k.toString().equalsIgnoreCase(search)) {
// ((JSONObject) parent).put(search, "TEST_A_NEW_VALUE");
((JSONObject) parent).put(search + "_new", "TEST_A_NEW_VALUE");
}
}
} catch (Exception ex) { // throws ConcurrentModificationException
ex.getMessage();
} finally {
}
} // iterate
The Starting json:
{
"data": {
"group": {
"subGroup": {
"boolean": {
"name": "test",
"description": "test",
"label": "test"
},
"description": "test",
"label": "test",
"text": {
"name": "test",
"description": "test",
"label": "test"
},
"choice": {
"name": "test",
"description": "test",
"label": "test",
"items": {
"item": [
{
"label": "test"
},
{
"label": "test"
},
{
"label": "test"
}
]
}
}
},
"name": "test",
"description": "test",
"label": "test"
}
}
}
The current output. While iterating, I get an ConcurrentModificationException.
label within item is not updated. But that is want I want.
{
"data": {
"group": {
"subGroup": {
"description": "test",
"label": "test",
"choice": {
"name": "test",
"description": "test",
"label": "test",
"items": {
"item": [
{
"label": "test",
"label_new": "TEST_A_NEW_VALUE"
},
{
"label": "test",
"label_new": "TEST_A_NEW_VALUE"
},
{
"label": "test",
"label_new": "TEST_A_NEW_VALUE"
}
]
}
},
"label_new": "TEST_A_NEW_VALUE"
},
"name": "test",
"description": "test",
"label": "test",
"label_new": "TEST_A_NEW_VALUE"
}
}
}
First, pass parent as a parameter, it makes more sense, and having it as a global variable may be prone to errors.
Second, to avoid concurrent modification, insert the new key after traversing the object:
if (obj instanceof JSONObject) {
boolean found = false;
for (Iterator it = ((JSONObject) obj).keys(); it.hasNext();) {
k = it.next();
v = ((JSONObject) obj).get((String) k);
if (v instanceof JSONArray || v instanceof JSONObject) {
iterate(v, obj, props, search); // second parameter is the parent
} else if (v instanceof String) {
if (!found && search.equalsIgnoreCase(v)) {
found = true;
}
}
}
if (found) {
// insert 'new' entry
}
}

How to simplify grouping of data to n times by using Map recursion in java?

I want to return a group of groups to n times in the following ways;
[
{
"field": "TestContacts_CompanyName",
"value": "MC 1",
"hasSubgroups": true,
"items": [
{
"field": "TestContacts_ID",
"value": "25",
"hasSubgroups": false,
"items": [
{
"TestContacts_ID": "25",
"TestContacts_CompanyName": "MC 1"
}
]
},
{
"field": "TestContacts_ID",
"value": "26",
"hasSubgroups": false,
"items": [
{
"TestContacts_ID": "26",
"TestContacts_CompanyName": "MC 1"
}
]
},
{
"field": "TestContacts_ID",
"value": "27",
"hasSubgroups": false,
"items": [
{
"TestContacts_ID": "27",
"TestContacts_CompanyName": "MC 1"
}
]
}
]
},
{
"field": "TestContacts_CompanyName",
"value": "MC 2",
"hasSubgroups": true,
"items": [
{ "field": "TestContacts_ID",
"value": "28",
"hasSubgroups": false,
"items": [
{
"TestContacts_ID": "28",
"TestContacts_CompanyName": "MC 2"
}
]
}
]
}
]
I don't want to use collectors.groupingby
public static JSONArray groupedArray(ArrayList<String> groupField,JSONArray itemsArray) throws Exception {
JSONArray itemArrayTemp = new JSONArray();
int i=0;
for (Map.Entry<String,ArrayList<Object>> entry : SLQUtil.groupData(groupField.get(i),itemsArray).entrySet()) {
JSONObject itemTemp = new JSONObject();
itemTemp.put("field",groupField.get(i) );
itemTemp.put("value",entry.getKey() );
if((groupField.size()-i ==1)){
itemTemp.put("hasSubgroups",false );//Single level grouping
itemTemp.put("items",entry.getValue() );
}else if((groupField.size()-i > 1)){
itemTemp.put("hasSubgroups",true );//2nd level grouping
JSONArray jsArray2 = new JSONArray(entry.getValue());//converting array list to json array
JSONArray itemArrayTemp2 = new JSONArray();
for (Map.Entry<String,ArrayList<Object>> entry2 : SLQUtil.groupData(groupField.get(i+1),jsArray2).entrySet()) {
JSONObject itemTemp2 = new JSONObject();
itemTemp2.put("field",groupField.get(i+1));
itemTemp2.put("value",entry2.getKey() );
itemTemp2.put("hasSubgroups",false );
itemTemp2.put("items",entry2.getValue() );
itemArrayTemp2.put(itemTemp2 );//2nd level of grouped data
}
itemTemp.put("items",itemArrayTemp2 );
}
itemArrayTemp.put(itemTemp);//1st level of grouped data
}
return itemArrayTemp;
}
public static Map<String, ArrayList<Object>> groupData(String field,JSONArray itemsArray) throws Exception {
Map<String, ArrayList<Object>> itemMap = new LinkedHashMap<>();
for (int i=0;i<itemsArray.length();i++){
JSONObject itemTemp = itemsArray.getJSONObject(i);
if(!itemMap.containsKey(itemTemp.getString(field))){
itemMap.put(itemTemp.getString(field), new ArrayList<>());
}
itemMap.get(itemTemp.getString(field)).add(itemTemp);
}
return itemMap;
}
public static Map<String, Object> groupDataRecursive(String currentKey, Map<String, Object> map, Map<String, Object> out) throws SQLException, Exception {
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (entry.getValue() instanceof Map) {
groupDataRecursive(currentKey, (Map<String, Object>) entry.getValue(), out);
} else {
Map tempMap = SLQUtil.groupData(currentKey,(JSONArray)entry.getValue());
map.put( entry.getKey(),tempMap);
//out.put(currentKey + "." + entry.getKey(), entry.getValue());
}
}
return map;
}

Taking user input retrieving details from json file and print it in java

Data.json:
{"UniversalWord": {"UniversalWord": [
{
"uw_id": 1,
"HeadWord": {"word": "aare"},
"Restriction": {"SemanticRelations": {"feat": [
{
"att": "restriction_type",
"value": "iof"
},
{
"att": "target",
"val": " "
}
]}},
"NLDescription": {
"Gloss": {"feat": {
"att": "Description",
"val": "\"A RIVER IN NORTH CENTRAL SWITZERLAND THAT RUNS NORTHEAST INTO THE RHINE\""
}},
"Lemma": {"feat": {
"att": "word",
"val": "aare"
}},
"Example": {"feat": {
"att": "description",
"val": "\"\""
}}
},
"MetaInfo": {
"Frequency": {"freq": ""},
"UWSource": {"Source_id": "WORDNET"}
}
},
{
"uw_id": 2,
"HeadWord": {"word": "aarhus"},
"Restriction": {"SemanticRelations": {"feat": [
{
"att": "restriction_type",
"value": "iof"
},
{
"att": "target",
"val": " "
},
{
"att": "restriction_type",
"value": "equ"
},
{
"att": "target",
"val": " "
}
]}},
"NLDescription": {
"Gloss": {"feat": {
"att": "Description",
"val": "\"PORT CITY OF DENMARK IN EASTERN JUTLAND\""
}},
"Lemma": {"feat": {
"att": "word",
"val": "aarhus"
}},
"Example": {"feat": {
"att": "description",
"val": "\"\""
}}
},
"MetaInfo": {
"Frequency": {"freq": ""},
"UWSource": {"Source_id": "WORDNET"}
}
}
]}}
Required output:
Word Searched: aare
uwid = 1
headword = aare
semantic relation value = iof
target = ""
gloss = A RIVER IN NORTH CENTRAL SWITZERLAND THAT RUNS NORTHEAST INTO THE RHINE
lemma = aare
example = ""
frequency = ""
Source_ID = wordnet
code.java
public class SearchJson
{
public void SearchValueInJson(StringBuilder sb)
{
try
{
String jsonData = sb.toString();
JSONObject jobj = new JSONObject(jsonData);
Map<String,String> map = new HashMap<String,String>();
iterateJson(jobj,map);
System.out.println(map.toString());
}
catch(Exception e)
{
System.out.println(e);
}
}
public void iterateJson(JSONObject jobj,Map map)
{
for(Object o : jobj.keySet())
{
if(jobj.get(o.toString())instanceof JSONObject)
iterateJson(jobj.getJSONObject(o.toString()),map);
else
map.put(o.toString(), jobj.get(o.toString()));
}
}
}
this code i tried but it is not giving me expected output.
How to retrieve this information from the json file? I'm not getting the proper solution for it. Please give code for this. And assume that you don't know key values of data on that basis have to retrieve.
Check the below code snippet, this may solve your problem.
JSONObject jobj = new JSONObject(jsonData);
JSONArray arr = jobj.getJSONObject("UniversalWord").getJSONArray("UniversalWord");
for (int i = 0; i < arr.length(); i++)
{
String uw_id = arr.getJSONObject(i).getString("uw_id");
System.out.println(uw_id);
String headWord = arr.getJSONObject(i).getJSONObject("HeadWord").getString("word");
System.out.println(headWord);
String nLDescription = arr.getJSONObject(i).getJSONObject("NLDescription").getJSONObject("Gloss").getJSONObject("feat").getString("val");
System.out.println(nLDescription);
}

Json data using Hashmap and Array List

I am new to Java. I am fetching data from DB and adding into Hashmap and then the Hashmap data to Array List to obtain JSON data. But I am not getting the output as expected. Child values should be added to the Hashmap based on the parent.
Java code
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import com.google.gson.Gson;
public class HaspmapEx
{
public static void main(String[] args)
{
Connection connection = null;
PreparedStatement pst = null;
ResultSet rs = null;
PreparedStatement pst2 = null;
ResultSet rs2 = null;
ArrayList<Object> list = new ArrayList<Object>();
ArrayList<Object> list1 = new ArrayList<Object>();
LinkedHashMap<String, Object> outMap= new LinkedHashMap<String, Object>();
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
connection=DriverManager.getConnection(
"jdbc:oracle:thin:#localhost:1521:orcl","REF","REF");
String qstr = "select distinct PARENT_ORG_NAME from demo_org_data";
String qstr1 = "select distinct org_lev1,org_lev2 from demo_org_data";
pst=connection.prepareStatement(qstr);
rs=pst.executeQuery();
pst2 = connection.prepareStatement(qstr1);
rs2 = pst2.executeQuery();
while (rs.next()) {
LinkedHashMap<String, Object> category = new LinkedHashMap<String, Object>();
category.put("label", rs.getString(1));
while (rs2.next())
{
LinkedHashMap<String, Object> category1 = new LinkedHashMap<String, Object>();
LinkedHashMap<String, Object> category2 = new LinkedHashMap<String, Object>();
category1.put("label", rs2.getString(1));
category1.put("label", rs2.getString(2));
category1.put("category", category2);
list1.add(category1);
}
category.put("category",list1);
list.add(category);
}
}
catch (SQLException sql) {
System.out.println("SQLException occurred while fetching the data");
}
catch (Exception e) {
System.out.println("Exception occurred while fetching the data");
}
outMap.put("category", list);
System.out.println(new Gson().toJson(outMap).toString());
}
}
Output for the above Java code :
"category": [{
"label": "CEO",
"category": [{
"label": "CFO",
"category": {
"label": "Payables"
}
}, {
"label": "CFO",
"category": {
"label": "Receivables"
}
}, {
"label": "CIO",
"category": {
"label": "HR"
}
}, {
"label": "CIO",
"category": {
"label": "PR"
}
}, {
"label": "CTO",
"category": {
"label": "Architect"
}
}, {
"label": "CTO",
"category": {
"label": "Project Manager"
}
}, {
"label": "CTO",
"category": {
"label": "QA Manager"
}
}]
}]
}
I want the output as shown below. The Parent-Child relationship can be clearly seen in the JSON data below
"category": [{
"label": "CEO",
"category": [{
"label": "CTO",
"category": [{
"label": "Proj. Manager"
}, {
"label": "Q & A Manager"
}, {
"label": "Architect"
}]
}, {
"label": "CFO",
"category": [{
"label": "Payables"
}, {
"label": "Receivables"
}]
}, {
"label": "CIO",
"category": [{
"label": "PR"
}, {
"label": "HR"
}]
}]
}]
You need to keep a list of categories and search for past occurences of org_lev1. I added a seperate method for that.
see complete solution:
public static void main(String[] args)
{
Connection connection = null;
PreparedStatement pst = null;
ResultSet rs = null;
PreparedStatement pst2 = null;
ResultSet rs2 = null;
LinkedHashMap<String, Object> parentCategory = new LinkedHashMap<String, Object>();
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
connection=DriverManager.getConnection(
"jdbc:oracle:thin:#localhost:1521:orcl","REF","REF");
String qstr = "select distinct PARENT_ORG_NAME from demo_org_data";
String qstr1 = "select distinct org_lev1,org_lev2 from demo_org_data";
pst = connection.prepareStatement(qstr);
rs = pst.executeQuery();
pst2 = connection.prepareStatement(qstr1);
rs2 = pst2.executeQuery();
while (rs.next()) {
List<Map<String, Object>> parentList = new ArrayList<>();
parentCategory.put("label", rs.getString(1));
parentCategory.put("category", parentList);
while (rs2.next()) {
String org_lev1 = rs2.getString(1);
String org_lev2 = rs2.getString(2);
Map<String, Object> subCategory = searchCategoryByLabel(parentList, org_lev1);
if (subCategory == null) {
subCategory = new LinkedHashMap<String, Object>();
subCategory.put("label", org_lev1);
subCategory.put("category", new ArrayList<Map<String, String>>());
parentList.add(subCategory);
}
List<Map<String, String>> subList = (List<Map<String, String>>)subCategory.get("category");
subList.add(Collections.singletonMap("label", org_lev2));
}
}
} catch (SQLException sql) {
System.out.println("SQLException occurred while fetching the data");
}
catch (Exception e) {
System.out.println("Exception occurred while fetching the data");
}
Map<String, List<Map<String, Object>>> outMap =
Collections.singletonMap("category", Collections.singletonList(parentCategory));
System.out.println(new Gson().toJson(outMap).toString());
}
public static Map<String, Object> searchCategoryByLabel(List<Map<String, Object>> list, String label)
{
for (Map<String, Object> map : list) {
if (map.containsKey("label") && map.get("label").toString().equals(label)) {
return map;
}
}
return null;
}
I got output:
{"category":[{"label":"CEO","category":[{"label":"CTO","category":[{"label":"Q \u0026 A Manager"},{"label":"Architect"},{"label":"Proj. Manager"}]},{"label":"CFO","category":[{"label":"Payables"},{"label":"Receivables"}]},{"label":"CIO","category":[{"label":"PR"},{"label":"HR"}]}]}]}
(hope you will appriciate the time I took to develop this)
You define a new category map for each entry in rs, so you will end up with several category maps. You want to put them inside one map that contains the category map and also rs.getString(1) so you need to define another (different) Map<String, Object> (call it allCategories) before the main loop, and then put in it rs.getString(1) and also category once it is populated.

Categories