[英]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");
所以在這種情況下,我想結合Obj1
和Obj2
,要么制作一個全新的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));
}
}
使用此代碼,如果Obj1
和Obj2
之間有任何重復的鍵,則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.