如何合并两个JObject?

22

我有一个第一个JSON:

{
    "data": [{
      "id": "id1",
      "field": "field1"
    }],
    "paging": {
        "prev": "link1",
    }
}

还有第二个:

{
    "data": [{
      "id": "id2",
      "field": "field2"
    }],
    "paging": {
        "prev": "link2",
    }
}

我希望将这两个数据数组合并/联合起来,例如:

{
    "data": [{
      "id": "id1",
      "field": "field1"
    },
    {
      "id": "id2",
      "field": "field2"
    }]  
}

(我现在不在意分页)。

我该如何快速轻松地做到这一点?这是我的尝试:

var final = JsonConvert.SerializeObject(new { data = json1["data"].Union(json2["data"]) }, Newtonsoft.Json.Formatting.Indented).ToString();

但是会引发异常:'Newtonsoft.Json.Linq.JArray' 不包含 'Union' 的定义

4个回答

45

Newtonsoft.Json现在支持合并对象(旧链接)

var dataObject1 = JObject.Parse(@"{
    ""data"": [{
        ""id"": ""id1"",
        ""field"": ""field1""
    }],
    ""paging"": {
        ""prev"": ""link1"",
    }
}");
var dataObject2 = JObject.Parse(@"{
    ""data"": [{
        ""id"": ""id2"",
        ""field"": ""field2""
    }],
    ""paging"": {
        ""prev"": ""link2"",
    }
}");

var mergeSettings = new JsonMergeSettings
{
    MergeArrayHandling = MergeArrayHandling.Union
};

// method 1
(dataObject1.SelectToken("data") as JArray).Merge(dataObject2.SelectToken("data"), mergeSettings);
// method 2
//dataObject1.Merge(dataObject2, mergeSettings);
    
var mergedArray = dataObject1.SelectToken("data") as JArray;
    
Console.WriteLine(mergedArray.ToString(Formatting.None));

(使用脑部编译器进行了检查 ;))


我想提一下现代C#语法允许像dataObject1.SelectToken("data") as JArray这样丑陋的代码变得更加简洁:(JArray)dataObject1["data"] - el toro
个人而言,我更喜欢这种方式:if (dataObject1["data"] is JArray jsonArr)。因为它可以确保对象与类型匹配。否则,您可能会引入空对象引用异常。在我看来,防御性编程是最好的选择。 - ManselD
这个答案很有帮助,给了我一个提示,让我知道如何替换Javascript/ECMAScript的“spread”运算符来快速组合其他对象中的对象;现在我可以从其他JObject中合并一个JObject,太棒了! - Nate Anderson

13
JArray dataOfJson1=json1.SelectToken("data");

JArray dataofJson2=json2.SelectToken("data");

foreach(JObject innerData in dataofJson2) 
{
    dataOfJson1.Add(innerData);
}

json1对象的数据类型是什么? - NovaDev
json1和json2的数据类型都是JObject, JObject json1 = JObject.Parse(data1); // 第一个JSON字符串 JObject json2 = JObject.Parse(data2); // 第二个JSON字符串 - Dibu

5

对于那些(像我一样)无法使用新的JSON.net库的人,以下方法是我使用的。

public static JObject mergeJsonObjects(List<JObject> objects) {

    JObject json = new JObject();
    foreach(JObject JSONObject in objects) {
        foreach(var property in JSONObject) {
            string name = property.Key;
            JToken value = property.Value;

            json.Add(property.Key, property.Value);
        }
    }

    return json;
}

该方法接受一个JObject列表作为参数,返回一个单个的JObject,简单而有效。

3
只是好奇,内部foreach循环后面的两行代码有什么作用? string name = property.Key; JToken value = property.Value; 我猜它是为了调试或者其他用途,你通常会对这些值进行一些处理,但是你现在把它们删除了(并且忘记删除设置变量的代码)...但也许我漏掉了什么? - Psyrus
正确的 json.Add 指令是 json.Add(name, value); - undefined

3
一种可能的解决方案是:
class Container
{
    public List<IdField> data{get;set;}
}

class IdField
{
    public string id{get;set;}
    public string field{get;set;}
}


string s1 = "{ \"data\": [{ \"id\": \"id1\", \"field\": \"field1\" }], \"paging\": { \"prev\": \"link1\", } }";
string s2 = "{ \"data\": [{ \"id\": \"id2\", \"field\": \"field2\" }], \"paging\": { \"prev\": \"link2\", } }";

var d1 = JsonConvert.DeserializeObject<Container>(s1);
var d2 = JsonConvert.DeserializeObject<Container>(s2);

d1.data.AddRange(d2.data);

var result = JsonConvert.SerializeObject(d1);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接