JSONObject를 반복하는 방법?


312

나는 JSON 라이브러리를 사용합니다 JSONObject(필요한 경우 전환하지 않아도됩니다).

반복하는 방법을 알고 JSONArrays있지만 Facebook에서 JSON 데이터를 구문 분석 할 때 배열 만 얻지 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
   }
}


이것을 시도하십시오 : stackoverflow.com/a/56223923/10268067
steve moretz

답변:


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

20
jObject.keys ()는 반복적 인 색인 순서로 반복자를 반환합니다.
macio.Jun

77
@ macio.Jun 그럼에도 불구하고, 순서는 속성의지도에서 중요하지 않습니다 :에서 키 JSONObject순서가 있고 당신의 주장은 개인 구현의 단순한 반영이었다)
칼리 가리

6
모든 키가 순차적으로 필요할 때 사용해야 할 것은 무엇입니까?
예리한

11
약간의 흔들림 : 키 조회를 두 번 수행하지 않습니까? 'Object o = jObject.get (key)'를 수행 한 다음 get (key)를 다시 호출하지 않고도 유형을 확인한 후 사용하는 것이 좋습니다.
Tom

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

1
이 예제는 IteratingJava 에서처럼 실제로 이해되지는 않지만 꽤 잘 작동합니다! 감사.
Tim Visée

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

구식 사용하기 [2019 년 4 월 2 일 업데이트]

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는 불행히도 반복자를 사용하도록 강요합니다.
Amalgovinus

1
당신은 내 그러나 여기를 구했습니다!
Lukuluba

1
org.json.JSONObject에 keySet ()이 없습니다
Ridhuvarshan


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");.
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();아마도 아니오 jsonChildObject처럼 정의해야 JSONObject jsonChildObject = iterator.next();합니까?
kontur

1
이 솔루션이 마음에 들지만 선언 Iterator<JSONObject>하면 경고가 표시됩니다. 나는 그것을 일반적인 것으로 바꾸고 <?>에 대한 호출을 캐스팅합니다 next(). 또한 캐스트를 저장하는 getString("id")대신 사용 합니다 get("id").
RTF

9

org.json.JSONObject는 이제 keySet () 메소드를 가지고 있습니다.이 메소드는 a를 리턴 Set<String>하고 for-each로 쉽게 반복 될 수 있습니다.

for(String key : jsonObject.keySet())

이것이 가장 편리한 해결책이라고 생각합니다. 조언을 주셔서 감사합니다 :)
Yurii Rabeshko

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 : ...."는 컴파일되지 않으며 반복자에서 확인되지 않은 캐스트 경고를 피할 수있는 방법이없는 것 같습니다. 바보 반복자.
Amalgovinus

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

2

Java 8 및 lambda를 사용하면 더 깨끗합니다.

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

내가 얻을 "소비자에게 널에서 캐스트는 최소한의 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

한 번은 0 인덱싱 된 이후로 1 씩 증가해야하고 Mysql 자동 증가를 깨뜨리는 ID가있는 json이있었습니다.

따라서 각 객체에 대해이 코드를 작성했습니다-누군가에게 도움이 될 수 있습니다.

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 배열 또는 중첩 된 JSONObject가있을 수있는 JSON이있는 경우 실제 복잡성이 발생합니다. 다음 코드 스 니펫은 이러한 비즈니스 요구 사항을 처리합니다. 해시 맵과 중첩 JSONArrays와 JSONObjects를 모두 사용하는 계층 적 JSON을 사용하고 해시 맵의 데이터로 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이지만 여기서는이 변경이 호출자에게 다시 참조 될 때 참조 오브젝트가 전달됨을 알아야합니다.


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();
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.