2010-03-08 9 views
38

Ich nehme einige JSON aus zwei verschiedenen Quellen, ich am Ende mit zwei JSONObject s und ich möchte sie zu einem kombinieren.Merge (Concat) Mehrere JSONObjects

Daten:

"Object1": { 
    "Stringkey":"StringVal", 
    "ArrayKey": [Data0, Data1] 
} 

"Object2": { 
    "Stringkey":"StringVal", 
    "Stringkey":"StringVal", 
    "Stringkey":"StringVal", 
} 

-Code, mit http://json.org/java/ Bibliothek:

// jso1 and jso2 are some JSONObjects already instantiated 
JSONObject Obj1 = (JSONObject) jso.get("Object1"); 
JSONObject Obj2 = (JSONObject) jso.get("Object2"); 

So in dieser Situation würde Ich mag Obj1 und Obj2 kombinieren, entweder eine völlig neue JSONObject oder concat machen zu den anderen. Irgendwelche Ideen abgesehen davon, sie alle auseinander zu ziehen und einzeln hinzuzufügen von put s?

Antwort

37

invertieren Wenn Sie ein neues Objekt mit zwei Schlüsseln wollen, Object1 und Object2, können Sie tun:

JSONObject Obj1 = (JSONObject) jso1.get("Object1"); 
JSONObject Obj2 = (JSONObject) jso2.get("Object2"); 
JSONObject combined = new JSONObject(); 
combined.put("Object1", Obj1); 
combined.put("Object2", Obj2); 

Wenn Sie sie zusammenführen möchten, also zB ein Top-Level-Objekt verfügt über 5 Tasten (Stringkey1, ArrayKey, StringKey2, StringKey3, StringKey4), ich glaube, Sie manuell tun müssen:

JSONObject merged = new JSONObject(Obj1, JSONObject.getNames(Obj1)); 
for(String key : JSONObject.getNames(Obj2)) 
{ 
    merged.put(key, Obj2.get(key)); 
} 

Dieses viel einfacher wäre, wenn JSONObject Map implementiert und unterstützt putAll.

+0

Ich versuche, Ihr zweites Code-Snippet in Android zu verwenden, aber ich sehe keine statische Funktion getNames auf JSONObject. Wurde dies in einer neueren Version der org.json-Bibliothek hinzugefügt? –

+2

@AustynMahoney, nicht sicher über die Geschichte, aber für Android können Sie die Instanzmethode ['JSONObject.names'] (http://developer.android.com/reference/org/json/JSONObject.html#names%28 % 29). –

+0

@AustynMahoney Es war nicht da in Android JSON-Bibliothek Ich habe es schon versucht. Es wurde auch nicht in Android-Dokumentation erwähnt. Es wurde nur hier erwähnt http://www.json.org/javadoc/org/json/JSONObject.html – kishore

19

Sie können einen neuen JSONObject wie folgt erstellen:

JSONObject merged = new JSONObject(); 
JSONObject[] objs = new JSONObject[] { Obj1, Obj2 }; 
for (JSONObject obj : objs) { 
    Iterator it = obj.keys(); 
    while (it.hasNext()) { 
     String key = (String)it.next(); 
     merged.put(key, obj.get(key)); 
    } 
} 

Mit diesem Code, wenn Sie wiederholt Tasten zwischen Obj1 haben und Obj2 der Wert in Obj2 bleiben. Wenn Sie die Werte in Obj1 gehalten werden möchten, sollten Sie die Reihenfolge der Anordnung in Zeile 2

+0

ich über die statische Methode JSONObject.getNames wusste nicht, es ist der Code macht viel einfacher, siehe unten Matthew Antwort was den Code reduziert, der es benutzt. –

+0

In der ersten Zeile 'new' vor' JSONObject() 'hinzufügen, edit ist für unter 6 Zeichen nicht erlaubt. –

16

In einigen Fällen benötigen Sie eine tiefe Zusammenführung, d. H. Zusammenführen der Inhalte von Feldern mit identischen Namen (genau wie beim Kopieren von Ordnern in Windows). Diese Funktion kann hilfreich sein:

/** 
* Merge "source" into "target". If fields have equal name, merge them recursively. 
* @return the merged object (target). 
*/ 
public static JSONObject deepMerge(JSONObject source, JSONObject target) throws JSONException { 
    for (String key: JSONObject.getNames(source)) { 
      Object value = source.get(key); 
      if (!target.has(key)) { 
       // new value for "key": 
       target.put(key, value); 
      } else { 
       // existing value for "key" - recursively deep merge: 
       if (value instanceof JSONObject) { 
        JSONObject valueJson = (JSONObject)value; 
        deepMerge(valueJson, target.getJSONObject(key)); 
       } else { 
        target.put(key, value); 
       } 
      } 
    } 
    return target; 
} 



/** 
* demo program 
*/ 
public static void main(String[] args) throws JSONException { 
    JSONObject a = new JSONObject("{offer: {issue1: value1}, accept: true}"); 
    JSONObject b = new JSONObject("{offer: {issue2: value2}, reject: false}"); 
    System.out.println(a+ " + " + b+" = "+JsonUtils.deepMerge(a,b)); 
    // prints: 
    // {"accept":true,"offer":{"issue1":"value1"}} + {"reject":false,"offer":{"issue2":"value2"}} = {"reject":false,"accept":true,"offer":{"issue1":"value1","issue2":"value2"}} 
} 
+0

Was ist, wenn ein Wert in 'source' vom Typ JSONArray ist ?. In diesem Fall müssten wir dieses Array mit dem entsprechenden JSONArray des Zielobjekts zusammenführen. – pgoldweic

3

Diese Wrapper Methode hilft:

private static JSONObject merge(JSONObject... jsonObjects) throws JSONException { 

    JSONObject jsonObject = new JSONObject(); 

    for(JSONObject temp : jsonObjects){ 
     Iterator<String> keys = temp.keys(); 
     while(keys.hasNext()){ 
      String key = keys.next(); 
      jsonObject.put(key, temp.get(key)); 
     } 

    } 
    return jsonObject; 
} 
0

Neben @ erel Antwort, ich hatte diese bearbeiten zu machen (ich verwende org.json.simple) an die äußeren else für den Umgang mit JSONArray 's:

  // existing value for "key" - recursively deep merge: 
      if (value instanceof JSONObject) { 
       JSONObject valueJson = (JSONObject)value; 
       deepMerge(valueJson, (JSONObject) target.get(key)); 
      } 

      // insert each JSONArray's JSONObject in place 
      if (value instanceof JSONArray) { 
       ((JSONArray) value).forEach(
        jsonobj -> 
        ((JSONArray) target.get(key)).add(jsonobj)); 
      } 
      else { 
       target.put(key, value); 
      } 
0

Dank Erel. Hier ist eine Gson-Version.

/** 
* Merge "source" into "target". If fields have equal name, merge them recursively. 
* Null values in source will remove the field from the target. 
* Override target values with source values 
* Keys not supplied in source will remain unchanged in target 
* 
* @return the merged object (target). 
*/ 
public static JsonObject deepMerge(JsonObject source, JsonObject target) throws Exception { 

    for (Map.Entry<String,JsonElement> sourceEntry : source.entrySet()) { 
     String key = sourceEntry.getKey(); 
     JsonElement value = sourceEntry.getValue(); 
     if (!target.has(key)) { 
      //target does not have the same key, so perhaps it should be added to target 
      if (!value.isJsonNull()) //well, only add if the source value is not null 
      target.add(key, value); 
     } else { 
      if (!value.isJsonNull()) { 
       if (value.isJsonObject()) { 
        //source value is json object, start deep merge 
        deepMerge(value.getAsJsonObject(), target.get(key).getAsJsonObject()); 
       } else { 
        target.add(key,value); 
       } 
      } else { 
       target.remove(key); 
      } 
     } 
    } 
    return target; 
} 



/** 
* simple test 
*/ 
public static void main(String[] args) throws Exception { 
    JsonParser parser = new JsonParser(); 
    JsonObject a = null; 
    JsonObject b = null; 
    a = parser.parse("{offer: {issue1: null, issue2: null}, accept: true, reject: null}").getAsJsonObject(); 
    b = parser.parse("{offer: {issue2: value2}, reject: false}").getAsJsonObject(); 
    System.out.println(deepMerge(a,b)); 
    // prints: 
    // {"offer":{},"accept":true} 
    a = parser.parse("{offer: {issue1: value1}, accept: true, reject: null}").getAsJsonObject(); 
    b = parser.parse("{offer: {issue2: value2}, reject: false}").getAsJsonObject(); 
    System.out.println(deepMerge(a,b)); 
    // prints: 
    // {"offer":{"issue2":"value2","issue1":"value1"},"accept":true} 

} 
0

Ich verwendete Zeichenfolge, um neues Objekt an ein vorhandenes Objekt zu verketten.


private static void concatJSON() throws IOException, InterruptedException { 

    JSONParser parser = new JSONParser(); 
    Object obj = parser.parse(new FileReader(new File(Main.class.getResource("/file/user.json").toURI()))); 


    JSONObject jsonObj = (JSONObject) obj; //usernameJsonObj 

    String [] values = {"0.9" , Date.from(Calendar.getInstance().toInstant()).toLocaleString()}, 
      innermost = {"Accomplished", "LatestDate"}, 
      inner = {"Lesson1", "Lesson2", "Lesson3", "Lesson4"}; 
    String in = "Jayvee Villa"; 

    JSONObject jo1 = new JSONObject(); 
    for (int i = 0; i < innermost.length; i++) 
     jo1.put(innermost[i], values[i]); 

    JSONObject jo2 = new JSONObject(); 
    for (int i = 0; i < inner.length; i++) 
     jo2.put(inner[i], jo1); 

    JSONObject jo3 = new JSONObject(); 
    jo3.put(in, jo2); 

    String merger = jsonObj.toString().substring(0, jsonObj.toString().length()-1) + "," +jo3.toString().substring(1); 

    System.out.println(merger); 
    FileWriter pr = new FileWriter(file); 
    pr.write(merger); 
    pr.flush(); 
    pr.close(); 
} 
2

Ein fertiges Verfahren eine beliebige Anzahl von JSONObjects zu fusionieren:

/** 
* Merges given JSONObjects. Values for identical key names are merged 
* if they are objects, otherwise replaced by the latest occurence. 
* 
* @param jsons JSONObjects to merge. 
* 
* @return Merged JSONObject. 
*/ 
public static JSONObject merge(
    JSONObject[] jsons) { 

    JSONObject merged = new JSONObject(); 
    Object parameter; 

    for (JSONObject added : jsons) { 

    for (String key : toStringArrayList(added.names())) { 
     try { 

     parameter = added.get(key); 

     if (merged.has(key)) { 
      // Duplicate key found: 
      if (added.get(key) instanceof JSONObject) { 
      // Object - allowed to merge: 
      parameter = 
       merge(
       new JSONObject[]{ 
        (JSONObject) merged.get(key), 
        (JSONObject) added.get(key)}); 
      } 
     } 

     // Add or update value on duplicate key: 
     merged.put(
      key, 
      parameter); 

     } catch (JSONException e) { 
     e.printStackTrace(); 
     } 
    } 

    } 

    return merged; 
} 

/** 
* Convert JSONArray to ArrayList<String>. 
* 
* @param jsonArray Source JSONArray. 
* 
* @return Target ArrayList<String>. 
*/ 
public static ArrayList<String> toStringArrayList(JSONArray jsonArray) { 

    ArrayList<String> stringArray = new ArrayList<String>(); 
    int arrayIndex; 

    for (
    arrayIndex = 0; 
    arrayIndex < jsonArray.length(); 
    arrayIndex++) { 

    try { 
     stringArray.add(
     jsonArray.getString(arrayIndex)); 
    } catch (JSONException e) { 
     e.printStackTrace(); 
    } 
    } 

    return stringArray; 
} 
Verwandte Themen