在 Java 中合并 (Concat) 多个 JSONObjects
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2403132/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Merge (Concat) Multiple JSONObjects in Java
提问by DanInDC
I am consuming some JSON from two different sources, I end up with two JSONObject
s and I'd like to combine them into one.
我正在使用来自两个不同来源的一些 JSON,我最终得到了两个JSONObject
s,我想将它们合二为一。
Data:
数据:
"Object1": {
"Stringkey":"StringVal",
"ArrayKey": [Data0, Data1]
}
"Object2": {
"Stringkey":"StringVal",
"Stringkey":"StringVal",
"Stringkey":"StringVal",
}
Code, using http://json.org/java/library:
代码,使用http://json.org/java/库:
// jso1 and jso2 are some JSONObjects already instantiated
JSONObject Obj1 = (JSONObject) jso.get("Object1");
JSONObject Obj2 = (JSONObject) jso.get("Object2");
So in this situation I'd like to combine Obj1
and Obj2
, either to make a totally new JSONObject
or concat one to the other. Any ideas besides pulling them all apart and individually adding in by put
s?
所以在这种情况下,我想结合Obj1
和Obj2
,要么制作一个全新的,要么将JSONObject
一个连接到另一个。除了将它们全部分开并通过put
s单独添加之外,还有什么想法?
采纳答案by Matthew Flaschen
If you want a new object with two keys, Object1 and Object2, you can do:
如果你想要一个有两个键 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);
If you want to merge them, so e.g. a top level object has 5 keys (Stringkey1, ArrayKey, StringKey2, StringKey3, StringKey4), I think you have to do that manually:
如果您想合并它们,例如顶级对象有 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));
}
This would be a lot easier if JSONObject implemented Map, and supported putAll.
如果 JSONObject 实现Map并支持 putAll,这会容易得多。
回答by Santi P.
You can create a new JSONObject like this:
您可以像这样创建一个新的 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));
}
}
With this code, if you have any repeated keys between Obj1
and Obj2
the value in Obj2
will remain. If you want the values in Obj1
to be kept you should invert the order of the array in line 2.
使用此代码,如果您有任何重复的键Obj1
,Obj2
则值Obj2
将保留。如果您希望Obj1
保留in 中的值,您应该反转第 2 行中数组的顺序。
回答by Erel Segal-Halevi
In some cases you need a deep merge, i.e., merge the contents of fields with identical names (just like when copying folders in Windows). This function may be helpful:
在某些情况下,您需要深度合并,即合并具有相同名称的字段的内容(就像在 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"}}
}
回答by Dave Ranjan
This wrapper method will help :
这种包装方法将有助于:
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;
}
回答by jonayreyes
In addition to @erel's answer, I had to make this edit (I'm using org.json.simple
) to the outer else
for dealing with JSONArray
's:
除了@erel 的回答之外,我还org.json.simple
必须对外部进行此编辑(我正在使用)以else
处理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);
}
回答by user2651508
Thanks to Erel. Here is a Gson version.
感谢埃雷尔。这是一个 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}
}
回答by Jayvee Villa
I used string to concatenate new object to an existing object.
我使用字符串将新对象连接到现有对象。
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();
}
回答by Zon
A ready method to merge any number of JSONObjects:
合并任意数量的 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;
}
回答by noam aghai
For me that function worked:
对我来说,该功能有效:
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;
}
(notice) - this implementation of concataion of json is for import org.json.simple.JSONObject;
(注意) - 这个 json 连接的实现是为了导入 org.json.simple.JSONObject;
回答by Ondra ?i?ka
Merging typed data structure trees is not trivial, you need to define the precedence, handle incompatible types, define how they will be casted and merged...
合并类型化数据结构树并非易事,您需要定义优先级,处理不兼容的类型,定义它们将如何转换和合并......
So in my opinion, you won't avoid
所以在我看来,你不会避免
... pulling them all apart and individually adding in by puts`.
...将它们全部分开并通过 puts 单独添加。
If your question is: Has someone done it for me yet?Then I think you can have a look at this YAML merging library/toolI revived. (YAML is a superset of JSON), and the principles are applicable to both.
(However, this particular code returns YAML objects, not JSON. Feel free to extend the project and send a PR.)
如果您的问题是:有人为我做过吗?那么我想你可以看看我复活的这个YAML 合并库/工具。(YAML 是 JSON 的超集),原则适用于两者。
(但是,此特定代码返回 YAML 对象,而不是 JSON。随意扩展项目并发送 PR。)