簡體   English   中英

在 Java 中合並(Concat)多個 JSONObject

[英]Merge (Concat) Multiple JSONObjects in Java

我正在使用來自兩個不同來源的一些 JSON,我最終得到了兩個JSONObject並且我想將它們組合成一個。

數據:

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

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

代碼,使用http://json.org/java/庫:

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

所以在這種情況下,我想結合Obj1Obj2 ,要么制作一個全新的JSONObject ,要么將一個連接到另一個。 除了將它們全部分開並通過put單獨添加之外,還有什么想法嗎?

如果您想要一個具有兩個鍵 Object1 和 Object2 的新對象,您可以執行以下操作:

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

如果您想合並它們,例如頂級對象有 5 個鍵(Stringkey1、ArrayKey、StringKey2、StringKey3、StringKey4),我認為您必須手動執行此操作:

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

如果 JSONObject 實現了Map並支持 putAll,這將容易得多。

在某些情況下,您需要深度合並,即合並具有相同名稱的字段的內容(就像在 Windows 中復制文件夾時一樣)。 此功能可能會有所幫助:

/**
 * 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"}}
}

您可以像這樣創建一個新的 JSONObject:

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

使用此代碼,如果Obj1Obj2之間有任何重復的鍵,則Obj2中的值將保留。 如果您希望保留Obj1中的值,則應反轉第 2 行中數組的順序。

這種包裝方法將有所幫助:

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

感謝埃雷爾。 這是一個 Gson 版本。

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

}

合並任意數量 JSONObject 的現成方法:

/**
 * 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;
}

這就是我所做的

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

/**
 * This class has all static functions to merge 2 objects into one
 */
public class MergeHelper {
    private static ObjectMapper objectMapper = new ObjectMapper();

    /**
     * return a merge JsonNode, merge newJson into oldJson; override or insert
     * fields from newJson into oldJson
     * 
     * @param oldJson
     * @param newJson
     * @return
     */
    public static JsonNode mergeJsonObject(JsonNode oldJson, JsonNode newJson) {
        ObjectNode merged = objectMapper.createObjectNode();
        merged.setAll((ObjectNode) oldJson);
        merged.setAll((ObjectNode) newJson);
        return merged;
    }
}

對我來說,該功能有效:

private static JSONObject concatJSONS(JSONObject json, JSONObject obj) {
    JSONObject result = new JSONObject();

    for(Object key: json.keySet()) {
        System.out.println("adding " + key + " to result json");
        result.put(key, json.get(key));
    }

    for(Object key: obj.keySet()) {
        System.out.println("adding " + key + " to result json");
        result.put(key, obj.get(key));
    }

    return result;
}

(注意)- json 連接的這種實現是用於導入org.json.simple.JSONObject;

除了else的回答之外,我還必須對外部進行此編輯(我正在使用org.json.simple )來處理JSONArray

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

我使用字符串將新對象連接到現有對象。


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

合並類型化的數據結構樹並非易事,您需要定義優先級、處理不兼容的類型、定義它們將如何轉換和合並......

所以在我看來,你不會避免

... 將它們全部分開並通過 puts 單獨添加。

如果您的問題是:有人為我做過嗎? 那我想你可以看看我復活的這個YAML 合並庫/工具 (YAML 是 JSON 的超集),這些原則適用於兩者。
(但是,此特定代碼返回 YAML 對象,而不是 JSON。請隨意擴展項目並發送 PR。)

今天,我也在努力合並 JSON 對象,並提供了以下解決方案(使用 Gson 庫)。

private JsonObject mergeJsons(List<JsonObject> jsonObjs) {
    JsonObject mergedJson = new JsonObject();
    jsonObjs.forEach((JsonObject jsonObj) -> {
        Set<Map.Entry<String, JsonElement>> entrySet = jsonObj.entrySet();
        entrySet.forEach((next) -> {
            mergedJson.add(next.getKey(), next.getValue());
        });
    });
    return mergedJson;
}

上面已經有人提到了。 我只會發布一個簡短的版本。

合並兩個 JSONObject json1 & json2你可以像這樣簡單地用 String 處理它:

String merged = json1.toString().substring(0, json1.length() - 1) + "," +
json2.toString().substring(1);
JSONObject mergedJson = new JSONObject(merged);

當然,不要忘記處理JSONException :) 希望這可以幫助你。

An improved version of merge on Gson's JsonObjects - can go any level of nested structure
 /**
 * Merge "source" into "target". 
 * 
 * <pre>
 *     An improved version of merge on Gson's JsonObjects - can go any level of nested structure:
 *             1. merge root & nested attributes.
 *             2. replace list of strings. For. eg.
 *              source -> "listOfStrings": ["A!"]
 *              dest -> "listOfStrings": ["A", "B"]
 *              merged -> "listOfStrings": ["A!", "B"]
 *             3. can merge nested objects inside list. For. eg.
 *              source -> "listOfObjects": [{"key2": "B"}]
 *              dest -> "listOfObjects": [{"key1": "A"}]
 *              merged -> "listOfObjects": [{"key1": "A"}, {"key2": "B"}]
 * </pre>
 * @return the merged object (target).
 */
public static JsonObject deepMerge(JsonObject source, JsonObject target) {
    for (String key: source.keySet()) {
        JsonElement srcValue = source.get(key);
        if (!target.has(key)) {
            target.add(key, srcValue);
        } else {
            if (srcValue instanceof JsonArray) {
                JsonArray srcArray = (JsonArray)srcValue;
                JsonArray destArray = target.getAsJsonArray(key);
                if (destArray == null || destArray.size() == 0) {
                    target.add(key, srcArray);
                    continue;
                } else {
                    IntStream.range(0, srcArray.size()).forEach(index -> {
                        JsonElement srcElem = srcArray.get(index);
                        JsonElement destElem = null;
                        if (index < destArray.size()) {
                            destElem = destArray.get(index);
                        }
                        if (srcElem instanceof JsonObject) {
                            if (destElem == null) {
                                destElem = new JsonObject();
                            }
                            deepMerge((JsonObject) srcElem, (JsonObject) destElem);
                        } else {
                            destArray.set(index, srcElem);
                        }
                    });
                }
            } else if (srcValue instanceof JsonObject) {
                JsonObject valueJson = (JsonObject)srcValue;
                deepMerge(valueJson, target.getAsJsonObject(key));
            } else {
                target.add(key, srcValue);
            }
        }
    }
    return target;
}

這個問題有一段時間了,但現在 JSONObject 實現了“toMap”方法,所以你可以嘗試這種方式:

Map<String, Object> map = Obj1.toMap();      //making an HashMap from obj1
map.putAll(Obj2.toMap());                    //moving all the stuff from obj2 to map
JSONObject combined = new JSONObject( map ); //new json from map

這是https://stackoverflow.com/a/15070484/9897317的一個版本,包括 JSONArrays :

/**
 * 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 (value != null) {
            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 if (value instanceof JSONArray) {
                    JSONArray arr = (JSONArray) value;
                    JSONArray newArr = new JSONArray();
                    for (int i = 0; i < arr.length(); i++) {
                        newArr.put(deepMerge(arr.getJSONObject(i), target.getJSONArray(key).getJSONObject(i)));
                    }
                    target.put(key, newArr);
                } else {
                    target.put(key, value);
                }
            }
        }
    }
    return target;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM