Comment itérer sur un JSONObject?

312

J'utilise une bibliothèque JSON appelée JSONObject(cela ne me dérange pas de changer si je le dois).

Je sais comment itérer dessus JSONArrays, mais lorsque j'analyse des données JSON de Facebook, je n'obtiens pas de tableau, seulement un JSONObject, mais je dois pouvoir accéder à un élément via son index, par exemple JSONObject[0]pour obtenir le premier, et je ne peut pas comprendre comment le faire.

{
   "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
la source

Réponses:

594

Peut-être que cela aidera:

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
la source
20
Soyez prudent tout le monde, jObject.keys () renvoie l'itérateur avec un ordre d'index inverse.
macio.juin
77
@ macio.Jun Néanmoins, l'ordre n'a pas d'importance dans les cartes de propriétés: les clés ne JSONObjectsont pas ordonnées et votre assertion était un simple reflet d'une implémentation privée;)
caligari
6
Que faut-il utiliser lorsque nous avons besoin de toutes les clés de manière séquentielle?
vif
11
Légère question: cela ne conduit-il pas à effectuer deux fois la recherche de touches? Il vaut peut-être mieux faire «Object o = jObject.get (key)», puis vérifier son type et l'utiliser, sans avoir à appeler à nouveau get (key).
Tom
1
Les boucles @Tom For-Each sont utiles lors de l'itération sur une collection:for (String key : keys)
caligari
86

pour mon cas, j'ai trouvé que les names()travaux étaient bien

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
la source
1
Bien que cet exemple ne soit pas vraiment compris comme Iteratingen Java, il fonctionne plutôt bien! Merci.
Tim Visée
57

J'éviterai l'itérateur car ils peuvent ajouter / supprimer un objet pendant l'itération, également pour une utilisation propre du code pour la boucle. ce sera tout simplement propre et moins de lignes.

Utilisation de Java 8 et Lamda [Mise à jour 4/2/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);
    });
}

Utiliser l'ancienne méthode [Mise à jour 4/2/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);
    }
}

Réponse originale

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
la source
5
Ils n'ont jamais dit qu'ils utilisaient org.json.simple (qui est une bibliothèque Google). Malheureusement, l'org.json.JSONObject standard vous oblige à utiliser un itérateur.
Amalgovinus
1
Vous m'avez sauvé mais ici!
Lukuluba
1
org.json.JSONObject n'a pas keySet ()
Ridhuvarshan
38

Je ne peux pas croire qu'il n'y ait pas de solution plus simple et sécurisée que d'utiliser un itérateur dans ces réponses ...

La names ()méthode JSONObject renvoie une JSONArraydes JSONObjectclés, vous pouvez donc simplement la parcourir en boucle:

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
la source
1
quel est l'objet ici?
RCS
1
Ça l'est JSONObject. Quelque chose comme JSONObject object = new JSONObject ("{\"key1\",\"value1\"}");. Mais ne mettez pas JSON cru, y ajouter des éléments dans avec put ()méthode: 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
la source
jsonChildObject = iterator.next();devrait probablement définir jsonChildObject, comme JSONObject jsonChildObject = iterator.next();, non?
kontur
1
J'aime cette solution, mais déclarer Iterator<JSONObject>donnera un avertissement. Je le remplacerais par le générique <?>et ferais un casting sur l'appel à next(). En outre, j'utiliserais getString("id")au lieu d' get("id")enregistrer pour faire un casting.
RTF
9

org.json.JSONObject a maintenant une méthode keySet () qui retourne un Set<String>et peut facilement être bouclée avec un for-each.

for(String key : jsonObject.keySet())
Burrito
la source
Je pense que c'est la solution la plus pratique. Merci pour les conseils :)
Yurii Rabeshko
1
Pourriez-vous compléter votre exemple?
gouffre
6

Mettez d'abord cela quelque part:

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

Ou si vous avez accès à Java8, juste ceci:

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

Ensuite, parcourez simplement les valeurs et les clés de l'objet:

for (String key : iteratorToIterable(object.keys())) {
    JSONObject entry = object.getJSONObject(key);
    // ...
Ebrahim Byagowi
la source
J'ai voté pour cela, mais "String key: ...." ne se compile pas, et il ne semble pas y avoir de moyen d'éviter un avertissement de cast non contrôlé sur l'itérateur. Itérateurs stupides.
Amalgovinus
2

J'ai créé une petite fonction récursive qui parcourt l'intégralité de l'objet json et enregistre le chemin de clé et sa valeur.

// 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
la source
2

Nous avons utilisé l'ensemble de code ci-dessous pour parcourir les JSONObjectchamps

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
la source
1

J'ai eu une fois un json qui avait des identifiants qui devaient être incrémentés d'un car ils étaient indexés 0 et cela cassait l'incrémentation automatique de Mysql.

Donc, pour chaque objet, j'ai écrit ce code - pourrait être utile à quelqu'un:

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

usage:

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

cela peut être transformé pour fonctionner pour JSONArray comme objet parent aussi

Michail Michailidis
la source
1

La plupart des réponses sont ici pour les structures JSON plates, au cas où vous auriez un JSON qui pourrait avoir des JSONArrays ou des JSONObjects imbriqués, la vraie complexité se pose. L'extrait de code suivant prend en charge une telle exigence métier. Il prend une carte de hachage et un JSON hiérarchique avec les JSONArrays et les JSONObjects imbriqués et met à jour le JSON avec les données de la carte de hachage

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

}

Vous devez remarquer ici que le type de retour de ceci est nul, mais les objets sice sont passés comme refernce ce changement est re-sélectionné à l'appelant.

Shekhar
la source
0

Le code ci-dessous a bien fonctionné pour moi. S'il vous plaît, aidez-moi si le réglage peut être fait. Cela obtient toutes les clés, même à partir des objets JSON imbriqués.

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
la source
-1

Ceci est une autre solution de travail au problème:

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
la source