Как перебрать JSONObject?

312

Я использую библиотеку JSON под названием JSONObject(я не против переключения, если мне нужно).

Я знаю, как перебирать JSONArrays, но когда я анализирую данные JSON из Facebook, я не получаю массив, только a JSONObject, но мне нужно иметь возможность получить доступ к элементу через его индекс, например, JSONObject[0]чтобы получить первый, и я не могу понять, как это сделать.

{
   "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
   }
}
Эрик Хьялмарссон
источник
1
Попробуйте это: androidbeasts.wordpress.com/2015/08/04/json-parsing-tutorial
Аакаш
попробуйте это: stackoverflow.com/a/56223923/10268067
Стив Моретц

Ответы:

594

Может быть, это поможет:

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
источник
20
Будьте внимательны, jObject.keys () возвращает итератор с обратным порядком индекса.
macio.Jun
77
@ macio.Jun Тем не менее, порядок не имеет значения в картах свойств: ключи JSONObjectнеупорядочены, и ваше утверждение было простым отражением частной реализации;)
caligari
6
Что использовать, когда нам нужны все ключи последовательно?
горячо
11
Незначительный спор: не приводит ли это к тому, что поиск ключа выполняется дважды? Может быть, лучше сделать 'Object o = jObject.get (key)', затем проверить его тип и затем использовать его, без необходимости повторного вызова get (key).
Том
1
Циклы @Tom For-Each полезны при итерации по коллекции:for (String key : keys)
caligari
86

для моего случая я нашел итерацию names()работ хорошо

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
источник
1
Хотя этот пример не совсем понятен, как Iteratingв Java, он работает довольно хорошо! Спасибо.
Тим Визе
57

Я буду избегать итераторов, поскольку они могут добавлять / удалять объекты во время итерации, а также для чистого использования кода для цикла. это будет просто чисто и меньше строк.

Использование Java 8 и Lamda [Обновление 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);
    });
}

Используя старый способ [Обновление 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);
    }
}

Оригинальный ответ

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);
    }
}
Маац
источник
5
Они никогда не говорили, что используют org.json.simple (это библиотека Google). К сожалению, стандартный org.json.JSONObject заставляет вас использовать итератор.
Амальговинус
1
Вы спасли меня, но здесь!
Лукулуба
1
org.json.JSONObject не имеет keySet ()
Ridhuvarshan
Какую версию вы ищете? stleary.github.io/JSON-java/org/json/JSONObject.html#keySet--
maaz
38

Не могу поверить, что нет более простого и безопасного решения, чем использование итератора в этих ответах ...

JSONObject names ()метод возвращает JSONArrayиз JSONObjectключей, так что вы можете просто ходить , хотя это в цикле:

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

}
Акуна
источник
1
что здесь за объект?
RCS
1
Это JSONObject. Нечто подобное JSONObject object = new JSONObject ("{\"key1\",\"value1\"}");. Но не помещайте сырец JSON к нему, добавлять элементы в нем с put ()методом: object.put ("key1", "value1");.
Акуна
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
источник
jsonChildObject = iterator.next();должно определиться jsonChildObject, вроде бы JSONObject jsonChildObject = iterator.next();, нет?
Контур
1
Мне нравится это решение, но объявление Iterator<JSONObject>даст предупреждение. Я бы заменил его на общий <?>и сделал бы вызов по вызову next(). Кроме того, я бы использовал getString("id")вместо того, get("id")чтобы сохранить, делая бросок.
RTF
9

org.json.JSONObject теперь имеет метод keySet (), который возвращает a Set<String>и может быть легко зациклен с помощью for-each.

for(String key : jsonObject.keySet())
буррито
источник
Я думаю, что это самое удобное решение. Спасибо за совет :)
Юрий Рабешко
1
Не могли бы вы завершить свой пример?
бездна
6

Сначала поместите это куда-нибудь:

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

Или, если у вас есть доступ к Java8, просто так:

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

Затем просто переберите ключи и значения объекта:

for (String key : iteratorToIterable(object.keys())) {
    JSONObject entry = object.getJSONObject(key);
    // ...
Эбрахим Бягови
источник
Я голосовал за это, но «String key: ....» не компилируется, и, похоже, не существует способа избежать неконтролируемого предупреждения приведения на итераторе. Глупые итераторы.
Амальговинус
2

Я сделал небольшую рекурсивную функцию, которая проходит через весь объект json и сохраняет путь к ключу и его значение.

// 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
источник
2

С Java 8 и лямбда, чище:

JSONObject jObject = new JSONObject(contents.trim());

jObject.keys().forEachRemaining(k ->
{

});

https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html#forEachRemaining-java.util.function.Consumer-

Томас Деко
источник
Он перебирает только ключи, но вам все еще нужно получить значение, поэтому вы можете использовать jObject.get (k);
Микель
Я получаю «Приведение от нуля к потребителю требует минимум API 24»
Harshil Pansare
2

Мы использовали ниже набор кода для перебора JSONObjectполей

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

while (iterator.hasNext())  {
        Entry<String, JsonElement> entry = (Entry<String, JsonElement>) iterator.next();
        processedJsonObject.add(entry.getKey(), entry.getValue());
}
Санчи Джиротра
источник
1

Однажды у меня был json, у которого были идентификаторы, которые нужно было увеличить на единицу, так как они были проиндексированы по 0, и это нарушало автоинкремент Mysql.

Таким образом, для каждого объекта, который я написал этот код - может быть полезным для кого-то:

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

использование:

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

это может быть преобразовано для работы для JSONArray как родительский объект

Михаил Михайлидис
источник
1

Большинство ответов здесь относятся к плоским структурам JSON. В случае, если у вас есть JSON, в котором могут быть вложенные JSONArrays или Nested JSONObjects, возникает реальная сложность. Следующий фрагмент кода заботится о таком требовании бизнеса. Он принимает хеш-карту и иерархический JSON с вложенными JSONArrays и JSONObjects и обновляет JSON с данными в хеш-карте

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

}

Здесь вы должны заметить, что тип возвращаемого значения void, но sice объекты передаются как ссылка, это изменение ссылается на вызывающую сторону.

Шекхар
источник
0

Ниже код работал нормально для меня. Пожалуйста, помогите мне, если настройка может быть выполнена. Это получает все ключи даже от вложенных объектов JSON.

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;
}
Рамджи Сридаран
источник
-1

Это еще одно рабочее решение проблемы:

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();
    }
}
Хай Тан Тонг
источник