Bagaimana cara mengulang melalui JSONObject?

312

Saya menggunakan perpustakaan JSON yang disebut JSONObject(Saya tidak keberatan beralih jika perlu).

Saya tahu cara mengulangi JSONArrays, tetapi ketika saya mem-parsing data JSON dari Facebook saya tidak mendapatkan array, hanya satu JSONObject, tapi saya harus dapat mengakses item melalui indeksnya, seperti JSONObject[0]untuk mendapatkan yang pertama, dan saya tidak tahu bagaimana melakukannya.

{
   "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
sumber

Jawaban:

594

Mungkin ini akan membantu:

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
sumber
20
Hati-hati semua orang, jObject.keys () mengembalikan iterator dengan urutan indeks terbalik.
macio.Jun
77
@ macio.Jun Namun demikian, urutannya tidak masalah di peta properti: kunci JSONObjecttidak berurutan dan pernyataan Anda adalah refleksi sederhana dari implementasi pribadi;)
caligari
6
Apa yang digunakan ketika kita membutuhkan semua kunci secara berurutan?
tajam
11
Berdalih sedikit: tidakkah ini menyebabkan melakukan pencarian kunci dua kali? Mungkin lebih baik melakukan 'Object o = jObject.get (key)', lalu periksa tipenya lalu gunakan, tanpa harus memanggil get (kunci) lagi.
Tom
1
@ Tom Untuk-Setiap loop berguna saat mengulang koleksi:for (String key : keys)
caligari
86

untuk kasus saya, saya menemukan iterasi names()bekerja dengan baik

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
sumber
1
Meskipun contoh ini tidak benar-benar dipahami seperti Iteratingdi Jawa, ini bekerja dengan sangat baik! Terima kasih.
Tim Visée
57

Saya akan menghindari iterator karena mereka dapat menambah / menghapus objek selama iterasi, juga untuk penggunaan kode bersih untuk loop. itu hanya akan bersih & lebih sedikit baris.

Menggunakan Java 8 dan Lamda [Pembaruan 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);
    });
}

Menggunakan cara lama [Pembaruan 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);
    }
}

Jawaban Asli

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
sumber
5
Mereka tidak pernah mengatakan bahwa mereka menggunakan org.json.simple (yang merupakan pustaka google). Sayangnya, standar org.json.JSONObject memaksa Anda untuk menggunakan iterator.
Amalgovinus
1
Anda menyelamatkan saya tetapi di sini!
Lukuluba
1
org.json.JSONObject tidak memiliki keySet ()
Ridhuvarshan
38

Tidak dapat percaya bahwa tidak ada solusi yang lebih sederhana dan aman daripada menggunakan iterator dalam jawaban ini ...

names ()Metode JSONObject mengembalikan a JSONArraydari JSONObjectkunci, sehingga Anda bisa berjalan meskipun dalam lingkaran:

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
sumber
1
apa objek di sini?
RCS
1
Ini JSONObject. Sesuatu seperti JSONObject object = new JSONObject ("{\"key1\",\"value1\"}");. Tetapi tidak menempatkan json baku untuk itu, menambahkan item di dalamnya dengan put ()metode: 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
sumber
jsonChildObject = iterator.next();mungkin harus mendefinisikan jsonChildObject, seperti JSONObject jsonChildObject = iterator.next();, tidak?
kontur
1
Saya suka solusi ini, tetapi menyatakan Iterator<JSONObject>akan memberi peringatan. Saya akan menggantinya dengan obat generik <?>dan melakukan panggilan pada next(). Juga, saya akan menggunakan getString("id")alih-alih get("id")menghemat melakukan pemeran.
RTF
9

org.json.JSONObject sekarang memiliki metode keySet () yang mengembalikan a Set<String>dan dapat dengan mudah dilingkari dengan masing-masing.

for(String key : jsonObject.keySet())
Burrito
sumber
Saya pikir ini adalah solusi yang paling nyaman. Terima kasih atas sarannya :)
Yurii Rabeshko
1
Bisakah Anda melengkapi contoh Anda?
jurang
6

Pertama-tama letakkan ini di suatu tempat:

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

Atau jika Anda memiliki akses ke Java8, cukup ini:

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

Kemudian cukup beralih pada kunci dan nilai objek:

for (String key : iteratorToIterable(object.keys())) {
    JSONObject entry = object.getJSONObject(key);
    // ...
Ebrahim Byagowi
sumber
Saya memilih ini, tetapi "Kunci string: ...." tidak dikompilasi, dan sepertinya tidak ada cara untuk menghindari peringatan pemain yang tidak dicentang pada iterator. Iterator bodoh.
Amalgovinus
2

Saya membuat fungsi rekursif kecil yang melewati seluruh objek json dan menyimpan jalur kunci dan nilainya.

// 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
sumber
2

Kami menggunakan serangkaian kode di bawah ini untuk beralih di atas JSONObjectbidang

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
sumber
1

Saya pernah punya json yang memiliki id yang perlu ditambah satu karena mereka diindeks 0 dan itu melanggar kenaikan otomatis Mysql.

Jadi untuk setiap objek saya menulis kode ini - mungkin dapat membantu seseorang:

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

pemakaian:

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

ini dapat diubah untuk bekerja untuk JSONArray sebagai objek induk juga

Michail Michailidis
sumber
1

Sebagian besar jawaban di sini adalah untuk struktur JSON datar, jika Anda memiliki JSON yang mungkin telah menyarangkan JSONArrays atau Nested JSONObjects, kompleksitas sebenarnya muncul. Cuplikan kode berikut menangani persyaratan bisnis seperti itu. Dibutuhkan peta hash, dan JSON hirarkis dengan JSONArrays bersarang dan JSONObjek dan memperbarui JSON dengan data di peta 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));
            }
        }
    });

}

Anda harus memperhatikan di sini bahwa tipe kembalinya ini batal, tetapi objek-objek sice dilewatkan sebagai rujukan perubahan ini dipantulkan kembali ke penelepon.

Shekhar
sumber
0

Kode di bawah ini berfungsi dengan baik untuk saya. Tolong bantu saya jika penyetelan bisa dilakukan. Ini mendapatkan semua kunci bahkan dari objek JSON bersarang.

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
sumber
-1

Ini adalah solusi lain untuk masalah ini:

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
sumber