Làm thế nào để lặp lại qua JSONObject?


312

Tôi sử dụng một thư viện JSON có tên JSONObject(Tôi không ngại chuyển đổi nếu tôi cần).

Tôi biết cách lặp lại JSONArrays, nhưng khi tôi phân tích dữ liệu JSON từ Facebook, tôi không nhận được một mảng, chỉ một JSONObject, nhưng tôi cần có thể truy cập một mục thông qua chỉ mục của nó, chẳng hạn như JSONObject[0]để có được mục đầu tiên và tôi không thể tìm ra cách để làm điều đó.

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


Câu trả lời:


594

Có thể điều này sẽ giúp:

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

20
Hãy cẩn thận với mọi người, jObject.keys () trả về iterator với thứ tự chỉ mục ngược lại.
macio.Jun

77
@ macio.Jun Tuy nhiên, thứ tự không quan trọng trong bản đồ các thuộc tính: các khóa trong JSONObjectkhông có thứ tự và khẳng định của bạn là sự phản ánh đơn giản của việc triển khai riêng tư;)
caligari

6
Sử dụng gì khi chúng ta cần tất cả các khóa liên tục?
quan tâm

11
Phân minh nhẹ: điều này không dẫn đến việc tra cứu chìa khóa hai lần? Có thể tốt hơn để làm 'Object o = jObject.get (key)', sau đó kiểm tra loại của nó và sau đó sử dụng nó, mà không phải gọi get (key) nữa.
Tom

1
@Tom For-Mỗi vòng lặp đều hữu ích khi lặp qua bộ sưu tập:for (String key : keys)
caligari

86

Đối với trường hợp của tôi, tôi thấy lặp đi lặp lại các names()công việc tốt

for(int i = 0; i<jobject.names().length(); i++){
    Log.v(TAG, "key = " + jobject.names().getString(i) + " value = " + jobject.get(jobject.names().getString(i)));
}

1
Mặc dù ví dụ này không thực sự được hiểu như Iteratingtrong Java, nhưng nó hoạt động khá tốt! Cảm ơn.
Tim Visée

57

Tôi sẽ tránh iterator vì chúng có thể thêm / xóa đối tượng trong quá trình lặp, cũng để sử dụng mã sạch cho vòng lặp. nó sẽ chỉ đơn giản là sạch sẽ & ít dòng hơn.

Sử dụng Java 8 và Lamda [Cập nhật 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);
    });
}

Sử dụng cách cũ [Cập nhật 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);
    }
}

Câu trả lời gốc

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
Họ không bao giờ nói rằng họ đang sử dụng org.json.simple (là một thư viện google). Thật không may, org.json.JSONObject buộc bạn phải sử dụng một trình vòng lặp, thật không may.
Amalgovinus

1
Bạn đã cứu tôi nhưng ở đây!
Lukuluba

1
org.json.JSONObject không có
keyset


38

Không thể tin rằng không có giải pháp đơn giản và bảo mật nào hơn là sử dụng một trình vòng lặp trong câu trả lời này ...

names ()Phương thức JSONObject trả về một JSONArraytrong các JSONObjectkhóa, vì vậy bạn chỉ cần đi bộ qua vòng lặp:

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
đối tượng ở đây là gì?
RCS

1
Đó là JSONObject. Một cái gì đó như JSONObject object = new JSONObject ("{\"key1\",\"value1\"}");. Nhưng đừng đặt json thô cho nó, hãy thêm các mục trong đó bằng put ()phương thức : 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");
}

jsonChildObject = iterator.next();Có lẽ nên định nghĩa jsonChildObject, thích JSONObject jsonChildObject = iterator.next();, không?
kontur

1
Tôi thích giải pháp này, nhưng tuyên bố Iterator<JSONObject>sẽ đưa ra cảnh báo. Tôi sẽ thay thế nó bằng cái chung <?>và thực hiện một cuộc gọi đến next(). Ngoài ra, tôi sẽ sử dụng getString("id")thay vì get("id")để lưu diễn viên.
RTF

9

org.json.JSONObject hiện có một phương thức keyset () trả về a Set<String>và có thể dễ dàng được lặp lại với mỗi for.

for(String key : jsonObject.keySet())

Tôi nghĩ rằng đây là giải pháp thuận tiện nhất. Cảm ơn vì lời khuyên :)
Yurii Rabeshko

1
Bạn có thể hoàn thành ví dụ của bạn?
khoảng cách

6

Đầu tiên đặt cái này ở đâu đó:

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

Hoặc nếu bạn có quyền truy cập vào Java8, chỉ cần điều này:

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

Sau đó, chỉ cần lặp lại các khóa và giá trị của đối tượng:

for (String key : iteratorToIterable(object.keys())) {
    JSONObject entry = object.getJSONObject(key);
    // ...

Tôi đã bình chọn cho điều này, nhưng "Chuỗi khóa: ...." không biên dịch và dường như không có cách nào để tránh cảnh báo bỏ chọn không được kiểm tra trên trình vòng lặp. Lặp đi lặp lại ngu ngốc.
Amalgovinus

2

Tôi đã thực hiện một hàm đệ quy nhỏ đi qua toàn bộ đối tượng json và lưu đường dẫn chính và giá trị của nó.

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

2

Với Java 8 và lambda, trình dọn dẹp:

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

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

});

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


Nó chỉ lặp lại các khóa nhưng bạn vẫn cần lấy giá trị, vì vậy bạn có thể sử dụng jObject.get (k);
Miquel

Tôi nhận được "Truyền từ null đến người tiêu dùng yêu cầu API tối thiểu 24"
Harshil Pansare

2

Chúng tôi đã sử dụng bộ mã dưới đây để lặp lại trên JSONObjectcác trường

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

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

1

Tôi đã từng có một json có id cần được tăng lên bởi vì chúng được lập chỉ mục 0 và điều đó đã phá vỡ mức tăng tự động của Mysql.

Vì vậy, đối với mỗi đối tượng tôi đã viết mã này - có thể hữu ích cho ai đó:

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

sử dụng:

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

điều này có thể được chuyển đổi để hoạt động cho JSONArray với tư cách là đối tượng cha


1

Hầu hết các câu trả lời ở đây là dành cho các cấu trúc JSON phẳng, trong trường hợp bạn có một JSON có thể có các hàm JSONArrays hoặc Nested JSONO lồng nhau, sự phức tạp thực sự nảy sinh. Đoạn mã sau đây đảm nhận một yêu cầu kinh doanh như vậy. Nó lấy một bản đồ băm và JSON phân cấp với cả JSONArrays và JSONObjects lồng nhau và cập nhật JSON với dữ liệu trong bản đồ băm

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

}

Bạn phải lưu ý ở đây rằng kiểu trả về của điều này là void, nhưng các đối tượng sice được thông qua khi giới thiệu thay đổi này được chọn lại cho người gọi.


0

Mã dưới đây làm việc tốt cho tôi. Xin hãy giúp tôi nếu điều chỉnh có thể được thực hiện. Điều này nhận được tất cả các khóa ngay cả từ các đối tượng JSON lồng nhau.

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

Đây là một giải pháp làm việc khác cho vấn đề:

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();
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.