Jackson Top

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE

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.

Jackson bottom

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE