Como iterar em um JSONObject?

312

Eu uso uma biblioteca JSON chamada JSONObject(não me importo de mudar, se necessário).

Eu sei como iterar JSONArrays, mas quando analiso dados JSON do Facebook, não recebo uma matriz, apenas a JSONObject, mas preciso acessar um item por meio de seu índice, como JSONObject[0]obter o primeiro, e eu não consigo descobrir como fazê-lo.

{
   "http://http://url.com/": {
      "id": "http://http://url.com//"
   },
   "http://url2.co/": {
      "id": "http://url2.com//",
      "shares": 16
   }
   ,
   "http://url3.com/": {
      "id": "http://url3.com//",
      "shares": 16
   }
}
Eric Hjalmarsson
fonte

Respostas:

594

Talvez isso ajude:

JSONObject jsonObject = new JSONObject(contents.trim());
Iterator<String> keys = jsonObject.keys();

while(keys.hasNext()) {
    String key = keys.next();
    if (jsonObject.get(key) instanceof JSONObject) {
          // do something with jsonObject here      
    }
}
Rickey
fonte
20
Cuidado com todo mundo, jObject.keys () retorna o iterador com ordem inversa do índice.
macio.Jun
77
@ macio.Jun No entanto, a ordem não importa em mapas de propriedades: chaves JSONObjectsão desordenadas e sua afirmação era um simples reflexo de uma implementação privada;)
caligari
6
O que usar quando precisamos de todas as chaves sequencialmente?
afiado
11
Ligeira reclamação: isso não leva a fazer a pesquisa de chave duas vezes? Talvez seja melhor fazer 'Object o = jObject.get (key)', verifique seu tipo e use-o, sem precisar chamar get (key) novamente.
Tom
1
@ Tom For-Cada voltas são úteis quando a iteração sobre uma coleção:for (String key : keys)
caligari
86

para o meu caso, achei iterando os names()trabalhos bem

for(int i = 0; i<jobject.names().length(); i++){
    Log.v(TAG, "key = " + jobject.names().getString(i) + " value = " + jobject.get(jobject.names().getString(i)));
}
AssemblyX
fonte
1
Embora este exemplo não seja realmente entendido como Iteratingem Java, ele funciona muito bem! Obrigado.
Tim Visée
57

Evitarei o iterador, pois eles podem adicionar / remover objetos durante a iteração, também para uso de código limpo para loop. será simplesmente limpo e menos linhas.

Usando Java 8 e Lamda [Atualização em 02/02/2019]

import org.json.JSONObject;

public static void printJsonObject(JSONObject jsonObj) {
    jsonObj.keySet().forEach(keyStr ->
    {
        Object keyvalue = jsonObj.get(keyStr);
        System.out.println("key: "+ keyStr + " value: " + keyvalue);

        //for nested objects iteration if required
        //if (keyvalue instanceof JSONObject)
        //    printJsonObject((JSONObject)keyvalue);
    });
}

Usando a maneira antiga [Atualização em 02/04/2019]

import org.json.JSONObject;

public static void printJsonObject(JSONObject jsonObj) {
    for (String keyStr : jsonObj.keySet()) {
        Object keyvalue = jsonObj.get(keyStr);

        //Print key and value
        System.out.println("key: "+ keyStr + " value: " + keyvalue);

        //for nested objects iteration if required
        //if (keyvalue instanceof JSONObject)
        //    printJsonObject((JSONObject)keyvalue);
    }
}

Resposta original

import org.json.simple.JSONObject;
public static void printJsonObject(JSONObject jsonObj) {
    for (Object key : jsonObj.keySet()) {
        //based on you key types
        String keyStr = (String)key;
        Object keyvalue = jsonObj.get(keyStr);

        //Print key and value
        System.out.println("key: "+ keyStr + " value: " + keyvalue);

        //for nested objects iteration if required
        if (keyvalue instanceof JSONObject)
            printJsonObject((JSONObject)keyvalue);
    }
}
maaz
fonte
5
Eles nunca disseram que estavam usando org.json.simple (que é uma biblioteca do Google). O org.json.JSONObject padrão força você a usar um iterador, infelizmente.
Amalgovinus
1
Você salvou o meu, mas aqui!
Lukuluba 18/09/17
1
não org.json.JSONObject não tem keySet ()
Ridhuvarshan
Qual versão você está procurando? stleary.github.io/JSON-java/org/json/JSONObject.html#keySet--
Maaz
38

Não posso acreditar que não há solução mais simples e segura do que usar um iterador nestas respostas ...

O names ()método JSONObject retorna uma JSONArraydas JSONObjectchaves, então você pode simplesmente caminhar por ele em loop:

JSONObject object = new JSONObject ();
JSONArray keys = object.names ();

for (int i = 0; i < keys.length (); ++i) {

   String key = keys.getString (i); // Here's your key
   String value = object.getString (key); // Here's your value

}
Acuna
fonte
1
o que é objeto aqui?
RCS
1
É JSONObject. Algo como JSONObject object = new JSONObject ("{\"key1\",\"value1\"}");. Mas não colocar json cru para ele, adicionar itens nele com put ()método: object.put ("key1", "value1");.
Acuna
18
Iterator<JSONObject> iterator = jsonObject.values().iterator();

while (iterator.hasNext()) {
 jsonChildObject = iterator.next();

 // Do whatever you want with jsonChildObject 

  String id = (String) jsonChildObject.get("id");
}
aviomaksim
fonte
jsonChildObject = iterator.next();provavelmente deveria definir jsonChildObject, tipo JSONObject jsonChildObject = iterator.next();, não?
21816 kontur
1
Eu gosto dessa solução, mas declarar Iterator<JSONObject>dará um aviso. Eu o substituiria pelo genérico <?>e faria uma chamada na chamada para next(). Além disso, eu usaria em getString("id")vez de get("id")economizar para fazer um elenco.
RTF
9

O org.json.JSONObject agora possui um método keySet () que retorna um Set<String>e pode ser facilmente repetido com um for-each.

for(String key : jsonObject.keySet())
Burrito
fonte
Eu acho que essa é a solução mais conveniente. Obrigado por conselho :)
Yurii Rabeshko
1
Você poderia completar seu exemplo?
abismo
6

Primeiro coloque isso em algum lugar:

private <T> Iterable<T> iteratorToIterable(final Iterator<T> iterator) {
    return new Iterable<T>() {
        @Override
        public Iterator<T> iterator() {
            return iterator;
        }
    };
}

Ou se você tiver acesso ao Java8, apenas isto:

private <T> Iterable<T> iteratorToIterable(Iterator<T> iterator) {
    return () -> iterator;
}

Em seguida, basta percorrer as chaves e os valores do objeto:

for (String key : iteratorToIterable(object.keys())) {
    JSONObject entry = object.getJSONObject(key);
    // ...
Ebrahim Byagowi
fonte
Votei a favor, mas "String key: ...." não é compilado e não parece haver uma maneira de evitar um aviso de elenco não verificado no iterador. Iteradores estúpidos.
Amalgovinus
2

Eu criei uma pequena função recursiva que percorre todo o objeto json e salva o caminho da chave e seu valor.

// My stored keys and values from the json object
HashMap<String,String> myKeyValues = new HashMap<String,String>();

// Used for constructing the path to the key in the json object
Stack<String> key_path = new Stack<String>();

// Recursive function that goes through a json object and stores 
// its key and values in the hashmap 
private void loadJson(JSONObject json){
    Iterator<?> json_keys = json.keys();

    while( json_keys.hasNext() ){
        String json_key = (String)json_keys.next();

        try{
            key_path.push(json_key);
            loadJson(json.getJSONObject(json_key));
       }catch (JSONException e){
           // Build the path to the key
           String key = "";
           for(String sub_key: key_path){
               key += sub_key+".";
           }
           key = key.substring(0,key.length()-1);

           System.out.println(key+": "+json.getString(json_key));
           key_path.pop();
           myKeyValues.put(key, json.getString(json_key));
        }
    }
    if(key_path.size() > 0){
        key_path.pop();
    }
}
Skullbox
fonte
2

Usamos abaixo o conjunto de códigos para iterar sobre os JSONObjectcampos

Iterator iterator = jsonObject.entrySet().iterator();

while (iterator.hasNext())  {
        Entry<String, JsonElement> entry = (Entry<String, JsonElement>) iterator.next();
        processedJsonObject.add(entry.getKey(), entry.getValue());
}
Sanchi Girotra
fonte
1

Certa vez, tive um json que tinha IDs que precisavam ser incrementados por um, uma vez que eram indexados a 0 e que estavam interrompendo o incremento automático do Mysql.

Portanto, para cada objeto que escrevi este código - pode ser útil para alguém:

public static void  incrementValue(JSONObject obj, List<String> keysToIncrementValue) {
        Set<String> keys = obj.keySet();
        for (String key : keys) {
            Object ob = obj.get(key);

            if (keysToIncrementValue.contains(key)) {
                obj.put(key, (Integer)obj.get(key) + 1);
            }

            if (ob instanceof JSONObject) {
                incrementValue((JSONObject) ob, keysToIncrementValue);
            }
            else if (ob instanceof JSONArray) {
                JSONArray arr = (JSONArray) ob;
                for (int i=0; i < arr.length(); i++) {
                    Object arrObj = arr.get(0);
                    if (arrObj instanceof JSONObject) {
                        incrementValue((JSONObject) arrObj, keysToIncrementValue);
                    }
                }
            }
        }
    }

uso:

JSONObject object = ....
incrementValue(object, Arrays.asList("id", "product_id", "category_id", "customer_id"));

isso pode ser transformado para funcionar também com JSONArray como objeto pai

Michail Michailidis
fonte
1

A maioria das respostas aqui são para estruturas JSON planas, caso você tenha um JSON que possa ter aninhado JSONArrays ou Nested JSONObjects, a complexidade real surgirá. O seguinte snippet de código cuida de um requisito comercial. Ele pega um mapa de hash e JSON hierárquico com JSONArrays e JSONObjects aninhados e atualiza o JSON com os dados no mapa de hash

public void updateData(JSONObject fullResponse, HashMap<String, String> mapToUpdate) {

    fullResponse.keySet().forEach(keyStr -> {
        Object keyvalue = fullResponse.get(keyStr);

        if (keyvalue instanceof JSONArray) {
            updateData(((JSONArray) keyvalue).getJSONObject(0), mapToUpdate);
        } else if (keyvalue instanceof JSONArray) {
            updateData((JSONObject) keyvalue, mapToUpdate);
        } else {
            // System.out.println("key: " + keyStr + " value: " + keyvalue);
            if (mapToUpdate.containsKey(keyStr)) {
                fullResponse.put(keyStr, mapToUpdate.get(keyStr));
            }
        }
    });

}

Você deve observar aqui que o tipo de retorno disso é nulo, mas os objetos do sice são passados ​​quando essa alteração é redirecionada para o chamador.

Shekhar
fonte
0

O código abaixo funcionou bem para mim. Por favor me ajude se o ajuste puder ser feito. Isso obtém todas as chaves mesmo dos objetos JSON aninhados.

public static void main(String args[]) {
    String s = ""; // Sample JSON to be parsed

    JSONParser parser = new JSONParser();
    JSONObject obj = null;
    try {
        obj = (JSONObject) parser.parse(s);
        @SuppressWarnings("unchecked")
        List<String> parameterKeys = new ArrayList<String>(obj.keySet());
        List<String>  result = null;
        List<String> keys = new ArrayList<>();
        for (String str : parameterKeys) {
            keys.add(str);
            result = this.addNestedKeys(obj, keys, str);
        }
        System.out.println(result.toString());
    } catch (ParseException e) {
        e.printStackTrace();
    }
}
public static List<String> addNestedKeys(JSONObject obj, List<String> keys, String key) {
    if (isNestedJsonAnArray(obj.get(key))) {
        JSONArray array = (JSONArray) obj.get(key);
        for (int i = 0; i < array.length(); i++) {
            try {
                JSONObject arrayObj = (JSONObject) array.get(i);
                List<String> list = new ArrayList<>(arrayObj.keySet());
                for (String s : list) {
                    putNestedKeysToList(keys, key, s);
                    addNestedKeys(arrayObj, keys, s);
                }
            } catch (JSONException e) {
                LOG.error("", e);
            }
        }
    } else if (isNestedJsonAnObject(obj.get(key))) {
        JSONObject arrayObj = (JSONObject) obj.get(key);
        List<String> nestedKeys = new ArrayList<>(arrayObj.keySet());
        for (String s : nestedKeys) {
            putNestedKeysToList(keys, key, s);
            addNestedKeys(arrayObj, keys, s);
        }
    }
    return keys;
}

private static void putNestedKeysToList(List<String> keys, String key, String s) {
    if (!keys.contains(key + Constants.JSON_KEY_SPLITTER + s)) {
        keys.add(key + Constants.JSON_KEY_SPLITTER + s);
    }
}



private static boolean isNestedJsonAnObject(Object object) {
    boolean bool = false;
    if (object instanceof JSONObject) {
        bool = true;
    }
    return bool;
}

private static boolean isNestedJsonAnArray(Object object) {
    boolean bool = false;
    if (object instanceof JSONArray) {
        bool = true;
    }
    return bool;
}
Ramji Sridaran
fonte
-1

Esta é outra solução funcional para o problema:

public void test (){

    Map<String, String> keyValueStore = new HasMap<>();
    Stack<String> keyPath = new Stack();
    JSONObject json = new JSONObject("thisYourJsonObject");
    keyValueStore = getAllXpathAndValueFromJsonObject(json, keyValueStore, keyPath);
    for(Map.Entry<String, String> map : keyValueStore.entrySet()) {
        System.out.println(map.getKey() + ":" + map.getValue());
    }   
}

public Map<String, String> getAllXpathAndValueFromJsonObject(JSONObject json, Map<String, String> keyValueStore, Stack<String> keyPath) {
    Set<String> jsonKeys = json.keySet();
    for (Object keyO : jsonKeys) {
        String key = (String) keyO;
        keyPath.push(key);
        Object object = json.get(key);

        if (object instanceof JSONObject) {
            getAllXpathAndValueFromJsonObject((JSONObject) object, keyValueStore, keyPath);
        }

        if (object instanceof JSONArray) {
            doJsonArray((JSONArray) object, keyPath, keyValueStore, json, key);
        }

        if (object instanceof String || object instanceof Boolean || object.equals(null)) {
            String keyStr = "";

            for (String keySub : keyPath) {
                keyStr += keySub + ".";
            }

            keyStr = keyStr.substring(0, keyStr.length() - 1);

            keyPath.pop();

            keyValueStore.put(keyStr, json.get(key).toString());
        }
    }

    if (keyPath.size() > 0) {
        keyPath.pop();
    }

    return keyValueStore;
}

public void doJsonArray(JSONArray object, Stack<String> keyPath, Map<String, String> keyValueStore, JSONObject json,
        String key) {
    JSONArray arr = (JSONArray) object;
    for (int i = 0; i < arr.length(); i++) {
        keyPath.push(Integer.toString(i));
        Object obj = arr.get(i);
        if (obj instanceof JSONObject) {
            getAllXpathAndValueFromJsonObject((JSONObject) obj, keyValueStore, keyPath);
        }

        if (obj instanceof JSONArray) {
            doJsonArray((JSONArray) obj, keyPath, keyValueStore, json, key);
        }

        if (obj instanceof String || obj instanceof Boolean || obj.equals(null)) {
            String keyStr = "";

            for (String keySub : keyPath) {
                keyStr += keySub + ".";
            }

            keyStr = keyStr.substring(0, keyStr.length() - 1);

            keyPath.pop();

            keyValueStore.put(keyStr , json.get(key).toString());
        }
    }
    if (keyPath.size() > 0) {
        keyPath.pop();
    }
}
Huy Thành Trương
fonte