Parse JSON object recursively - Java
Solution 1
As mentioned in my comment.
Your first issue would be the content in your JSON file. Based on the standard, it should be wrapped around with a set of { }.
Example
{
"members": [
{
"firstName": "Bruce",
"familyMembers": null
},
{
"firstName": "Gates Family",
"familyMembers": [
{
"firstName": "Bill",
"familyMembers": null
},
{
"firstName": "Steve",
"familyMembers": null
}
]
},
{
"firstName": "Lee",
"familyMembers": null
},
{
"firstName": "Chan",
"familyMembers": null
}
]
}
Also, I think the value "Gates Family" should be part of the output? Since it is under the "FirstName" attribute.
Anyway, here is my solution that is based on the org.json library. It also uses Goggle's GSon library where I use it for reading the JSON file.
import org.json.*;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
public class solution {
public static final String JSON_DATA_FILE_PATH = "./data/source_37848106.json";
private static boolean hasMoreFamilyName(JSONObject json) {
return json.has("familyMembers") && json.get("familyMembers") != JSONObject.NULL;
}
private static void trackFirstName(Map<String, Integer> nameTracker, JSONObject json) {
if (!nameTracker.containsKey(json.getString("firstName"))) {
nameTracker.put(json.getString("firstName"), /*DUMMY VALUE =*/1);
}
}
private static void getNames(Map<String,Integer> nameTracker, JSONArray jsonArr) {
for (int i = 0; i< jsonArr.length(); i++) {
JSONObject item = jsonArr.getJSONObject(i);
if (hasMoreFamilyName(item)) {
getNames(nameTracker, item.getJSONArray("familyMembers"));
}
trackFirstName(nameTracker, item);
}
}
public static void main(String[] args) {
Map<String, Integer> nameTracker = new HashMap<>();
try {
String text = Files.toString(new File(JSON_DATA_FILE_PATH), Charsets.UTF_8);
JSONObject json = new JSONObject(text);
getNames(nameTracker, json.getJSONArray("members"));
}
catch (Exception ex) {
System.out.println("Something is wrong.");
}
for (Map.Entry<String,Integer> entry : nameTracker.entrySet()) {
System.out.println(entry.getKey());
}
}
Solution 2
Try my recursive implementation.
public static void jsonArrayToSet(JSONArray jAry, Set<String> result, String targetKey, String subArrayKey, boolean includeNode){
try {
for (int i = 0; i < jAry.length(); i++) {
JSONObject jObj = jAry.getJSONObject(i);
boolean hasSubArray = false;
JSONArray subArray = null;
if(jObj.has(subArrayKey)){
Object possibleSubArray = jObj.get(subArrayKey);
if(possibleSubArray instanceof JSONArray){
hasSubArray = true;
subArray = (JSONArray) possibleSubArray;
}
}
if(hasSubArray){
if(includeNode){
result.add(jObj.getString(targetKey));
}
jsonArrayToSet(subArray, result, targetKey, subArrayKey, includeNode);
} else {
result.add(jObj.getString(targetKey));
}
}
} catch (JSONException e){
e.printStackTrace();
}
}
jAry
: The source JSONArray
.
result
: The Set
you want to write in.
targetKey
: The key that maps to an entry which you want to add to result
.
subArrayKey
: The key that map to a sub-JSONArray
.
includeNode
: When current JSONOnject
is a node containing sub-array, add it to result
or not.
In your case, you can call:
jsonArrayToSet(yourJsonArray, yourSet, "firstName", "familyMembers", false);
Shasti
Updated on June 04, 2022Comments
-
Shasti almost 2 years
I have a JSON with list of Objects and any of the item in the list can have null or the same object as a value for a key. I am looking for a faster way to parse the json to arrive at my final result. The data structure looks like -
[ { "firstName": "Bruce", "familyMembers": null }, { "firstName": "Gates Family", "familyMembers": [ { "firstName": "Bill", "familyMembers": null }, { "firstName": "Steve", "familyMembers": null } ] }, { "firstName": "Lee", "familyMembers": null }, { "firstName": "Chan", "familyMembers": null } ]
The output should be a set = ("Bruce", "Bill", "Steve", "Lee", "Chan").
I am looking for a best possible way to do this in Java, such that i dont increase my response time by getting caught in this parsing hell. Appreciate your time on this.
-
Samuel Toh almost 8 yearsPossibly a duplicate of stackoverflow.com/questions/2591098/how-to-parse-json-in-java
-
jtahlborn almost 8 yearsuse jackson's stream parser.
-
Samuel Toh almost 8 yearsOn a side note. The file that you have up there does not comply to the JSON standard because the content should begin with the { } clause. E.g. { member: [ {1:2}, {3:4} ] }
-
Samuel Toh almost 8 yearsAlso, should the string "GatesFamily" be included into the set? Because that is reflected as the "firstName" attribute.
-