C#中合并含内部数组的JSON数组,实现匹配键值覆盖
自定义JSON数组合并:按指定键匹配替换内层项
问题场景
现有两个嵌套结构的JSON数组:
第一个JSON数组
[{"name":"a","innerArray":[{"first":1,"second":1},{"first":2,"second":2}]},{"name":"b","innerArray":[{"first":1,"second":1},{"first":2,"second":2}]}]
第二个JSON数组
[{"name":"a","innerArray":[{"first":1,"second":11},{"first":3,"second":22}]},{"name":"c","innerArray":[{"first":1,"second":1},{"first":2,"second":2}]}]
期望合并规则:
- 外层数组按
name字段匹配,存在则合并内部数组,不存在则新增 - 内部
innerArray按first字段匹配:相同first值的项用第二个数组的内容覆盖,第二个数组里不存在的first值保留原项,新增第二个数组里独有的项
使用Json.NET默认的Merge方法(设置MergeArrayHandling.Union)无法实现该逻辑,因为它会直接替换整个内部数组,而非按指定键匹配替换。
解决方案:自定义合并逻辑
通过手动遍历、字典映射的方式实现精准匹配合并,代码示例如下:
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System.Collections.Generic; using System.Linq; class Program { static void Main() { // 原始JSON字符串 string json1 = @"[{""name"":""a"",""innerArray"":[{""first"":1,""second"":1},{""first"":2,""second"":2}]},{""name"":""b"",""innerArray"":[{""first"":1,""second"":1},{""first"":2,""second"":2}]}]"; string json2 = @"[{""name"":""a"",""innerArray"":[{""first"":1,""second"":11},{""first"":3,""second"":22}]},{""name"":""c"",""innerArray"":[{""first"":1,""second"":1},{""first"":2,""second"":2}]}]"; // 解析为JArray JArray arr1 = JArray.Parse(json1); JArray arr2 = JArray.Parse(json2); // 外层转换为name为键的字典,方便匹配 var dict1 = arr1.ToDictionary(item => item["name"].ToString(), item => item); var dict2 = arr2.ToDictionary(item => item["name"].ToString(), item => item); foreach (var kvp in dict2) { string name = kvp.Key; JObject targetObj = kvp.Value as JObject; if (dict1.ContainsKey(name)) { // 存在相同name,合并innerArray JObject sourceObj = dict1[name] as JObject; JArray sourceInner = sourceObj["innerArray"] as JArray; JArray targetInner = targetObj["innerArray"] as JArray; // 把内层数组转为first为键的字典 var innerDict = sourceInner.ToDictionary(item => item["first"].Value<int>(), item => item); // 遍历目标内层数组,替换或新增项 foreach (JObject innerItem in targetInner) { int first = innerItem["first"].Value<int>(); innerDict[first] = innerItem; // 覆盖已有项,新增不存在的项 } // 转换回JArray,保持有序 var mergedInner = new JArray(innerDict.OrderBy(k => k.Key).Select(k => k.Value)); sourceObj["innerArray"] = mergedInner; } else { // 不存在则直接添加 dict1.Add(name, targetObj); } } // 转换回JArray并输出 JArray mergedResult = new JArray(dict1.Values.OrderBy(item => item["name"].ToString())); Console.WriteLine(mergedResult.ToString(Formatting.Indented)); } }
输出结果
运行上述代码后,输出的合并结果与预期一致:
[ { "name": "a", "innerArray": [ { "first": 1, "second": 11 }, { "first": 2, "second": 2 }, { "first": 3, "second": 22 } ] }, { "name": "b", "innerArray": [ { "first": 1, "second": 1 }, { "first": 2, "second": 2 } ] }, { "name": "c", "innerArray": [ { "first": 1, "second": 1 }, { "first": 2, "second": 2 } ] } ]
内容的提问来源于stack exchange,提问作者Dev G
相关产品推荐
相关产品推荐

