Iterando sobre uma Instância de org.json.JSONObject

Iterando sobre uma Instância de org.json.JSONObject

1. Introdução

Neste tutorial, veremos algumas abordagens para iterar emJSONObject, uma representação JSON simples para Java.

Vamos começar com uma solução ingênua e, em seguida, olhar para algo um pouco mais robusto.

2. Iterando por meio de umJSONObject

Vamos começar com o caso simples de iterar um JSON de pares nome-valor:

{
  "name": "Cake",
  "cakeId": "0001",
  "cakeShape": "Heart"
}

Para isso, podemos simplesmenteiterate 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);
    }
}

E nossa saída será:

Key: name      Value: Cake
Key: cakeId    Value: 0001
Key: cakeShape Value: Heart

3. Atravessando umJSONObject

Mas digamos que temos uma estrutura mais complexa:

{
  "batters": [
    {
      "type": "Regular",
      "id": "1001"
    },
    {
      "type": "Chocolate",
      "id": "1002"
    },
    {
      "type": "BlueBerry",
      "id": "1003"
    }
  ],
  "name": "Cake",
  "cakeId": "0001"
}

O que a iteração pelas chaves significa nesse caso?

Vamos dar uma olhada no que nossa abordagem ingênuakeys() nos daria:

Key: batters    Value: [{"type":"Regular","id":"1001"},{"type":"Chocolate","id":"1002"},
  {"type":"BlueBerry","id":"1003"}]
Key: name       Value: Cake
Key: cakeId     Value: 0001

Isso, talvez, não seja tão útil. Parece quewe want in this case is not iteration, but instead traversal.

Percorrer umJSONObject é diferente de percorrer um conjunto de chaves deJSONObject.

Para isso,we actually need to check the value type, too. Vamos imaginar que fazemos isso em um método separado:

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

Então, nossa abordagem ainda é bastante semelhante:

void handleJSONObject(JSONObject jsonObject) {
    jsonObject.keys().forEachRemaining(key -> {
        Object value = jsonObject.get(key);
        logger.info("Key: {0}", key);
        handleValue(value);
    });
}

A única coisa é que precisamos pensar em como lidar com matrizes.

4. Atravessando umJSONArray

Vamos tentar manter uma abordagem semelhante de uso de um iterador. Instead of calling keys(), though, we’ll call iterator():

void handleJSONArray(JSONArray jsonArray) {
    jsonArray.iterator().forEachRemaining(element -> {
        handleValue(element)
    });
}

Agora, essa solução é limitante porquewe are combining traversal with the action we want to take. Uma abordagem comum para separar os dois seria usarVisitor pattern.

5. Conclusão

Neste artigo, vimos uma maneira de iterar emJSONObject para pares nome-valor simples, o problema associado a estruturas complexas e uma técnica de passagem para resolvê-lo.

Claro,this was a depth-first traversal method, but we could do breadth-first de maneira semelhante.

O código completo para o exemplo está disponívelover on Github.