Слияние (Concat) нескольких JSONObjects в 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
или concat один для другого. Любые идеи, кроме того, что они отделяют их друг от друга и индивидуально добавляются в put
s?
Ответы
Ответ 1
Если вам нужен новый объект с двумя ключами 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.
Ответ 2
Вы можете создать новый 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.
Ответ 3
В некоторых случаях вам необходимо глубокое слияние, т.е. объединить содержимое полей с одинаковыми именами (точно так же, как при копировании папок в 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"}}
}
Ответ 4
Этот метод обертки поможет:
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;
}
Ответ 5
Готовый метод для объединения любого числа JSONObjects:
/**
* 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;
}
Ответ 6
Благодаря Эрелю. Вот версия 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}
}
Ответ 7
В дополнение к ответу @erel мне пришлось сделать это редактирование (я использую org.json.simple
) для внешнего else
для работы с 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 JSONObject in place
if (value instanceof JSONArray) {
((JSONArray) value).forEach(
jsonobj ->
((JSONArray) target.get(key)).add(jsonobj));
}
else {
target.put(key, value);
}
Ответ 8
Я использовал строку, чтобы объединить новый объект с существующим объектом.
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();
}
Ответ 9
Для меня эта функция сработала:
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;
Ответ 10
Слияние деревьев структуры типизированных данных не является тривиальным, вам нужно определить приоритет, обработать несовместимые типы, определить, как они будут преобразованы и объединены...
Так что, на мой взгляд, вы не будете избегать
... раздвигая их друг от друга и индивидуально добавляя путами.
Если ваш вопрос: кто-то уже сделал это для меня? Тогда я думаю, что вы можете взглянуть на эту библиотеку/инструмент для слияния YAML, которую я восстановил. (YAML - это расширенный набор JSON), и принципы применимы к обоим.
(Однако этот конкретный код возвращает объекты YAML, а не JSON. Не стесняйтесь расширять проект и отправлять PR.)
Ответ 11
Сегодня я также изо всех сил пытался объединить объекты 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;
}
Ответ 12
Кто-то уже упоминал выше. Я просто выложу короткую версию.
Чтобы объединить два JSONObject json1
& json2
Вы можете просто разобраться со строкой следующим образом:
String merged = json1.toString().substring(0, json1.length() - 1) + "," +
json2.toString().substring(1);
JSONObject mergedJson = new JSONObject(merged);
Конечно, не забудьте разобраться с JSONException
. :)
Надеюсь, это поможет вам.