1. Introduction
In this tutorial, we’ll look at a couple of approaches for iterating over a JSONObject, a simple JSON representation for Java.
We’ll start with a naive solution and then look at something a little more robust.
2. Iterating Through a JSONObject
Let’s start with the simple case of iterating a JSON of name-value pairs:
{ "name": "Cake", "cakeId": "0001", "cakeShape": "Heart" }
For this, we can simply iterate through the keys using the keys() method:
void handleJSONObject(JSONObject jsonObject) { jsonObject.keys().forEachRemaining(key -> { Object value = jsonObject.get(key); logger.info("Key: {0}\tValue: {1}", key, value); } }
And our output will be:
Key: name Value: Cake Key: cakeId Value: 0001 Key: cakeShape Value: Heart
3. Traversing Through a JSONObject
But let’s say that we have a more complex structure:
{ "batters": [ { "type": "Regular", "id": "1001" }, { "type": "Chocolate", "id": "1002" }, { "type": "BlueBerry", "id": "1003" } ], "name": "Cake", "cakeId": "0001" }
What does iterating through the keys mean in this case?
Let’s take a look at what our naive keys() approach would give us:
Key: batters Value: [{"type":"Regular","id":"1001"},{"type":"Chocolate","id":"1002"}, {"type":"BlueBerry","id":"1003"}] Key: name Value: Cake Key: cakeId Value: 0001
This, perhaps, isn’t quite as helpful. It seems like what we want in this case is not iteration, but instead traversal.
Traversing through a JSONObject is different from iterating through a JSONObject‘s key set.
For this, we actually need to check the value type, too. Let imagine we do this in a separate method:
void handleValue(Object value) { if (value instanceof JSONObject) { handleJSONObject((JSONObject) value); } else if (value instanceof JSONArray) { handleJSONArray((JSONArray) value); } else { logger.info("Value: {0}", value); } }
Then, our approach is still fairly similar:
void handleJSONObject(JSONObject jsonObject) { jsonObject.keys().forEachRemaining(key -> { Object value = jsonObject.get(key); logger.info("Key: {0}", key); handleValue(value); }); }
The only thing is that we need to think about how to handle arrays.
4. Traversing Through a JSONArray
Let’s try and keep a similar approach of using an iterator. Instead of calling keys(), though, we’ll call iterator():
void handleJSONArray(JSONArray jsonArray) { jsonArray.iterator().forEachRemaining(element -> { handleValue(element) }); }
Now, this solution is limiting because we are combining traversal with the action we want to take. A common approach to separating the two would be using the Visitor pattern.
5. Conclusion
In this article, we saw a way to iterate over a JSONObject for simple name-value pairs, the problem associated with complex structures, and a traversal technique to solve it.
Of course, this was a depth-first traversal method, but we could do breadth-first in a similar way.
The complete code for the example is available over on Github.