C# 基于Newtonsoft.Json合并未知结构JSON并过滤Json2独有属性
Newtonsoft.Json 自定义规则合并JSON实现
合并规则要求
合并两个结构未知的JSON时,需遵循以下规则:
- 若某属性同时存在于两个JSON中,合并结果中该属性取Json2的值
- 若某属性仅存在于Json2中,合并结果不保留该属性
- 若某属性仅存在于Json1中,合并结果保留该属性
默认方法的问题
直接调用Newtonsoft.Json内置的JObject.Merge()方法时,会默认把Json2中独有的属性也加入结果,不符合预期,测试样例如下:
输入Json1
{ "FullName": "Dan Deleted", "Deleted": true, "DeletedDate": "2013-01-20T00:00:00", "location": { "nation": "it", "city": "Madrid" } }
输入Json2
{ "FullName": "Dan", "Age": "23", "DeletedDate": "2014-01-20T00:00:00", "location": { "nation": "es" } }
预期合并结果
{ "FullName": "Dan", "Deleted": true, "DeletedDate": "2014-01-20T00:00:00", "location": { "nation": "es", "city": "Madrid" } }
默认Merge输出结果
{ "FullName": "Dan", "Deleted": true, "DeletedDate": "2014-01-20T00:00:00", "location": { "nation": "es", "city": "Madrid" }, "Age": "23" }
可以看到结果中多出了Json2独有的Age字段,不符合规则要求。
自定义合并实现
核心逻辑是从Json1的结构出发做递归遍历,只处理两个JSON共有的属性,自动跳过Json2独有的属性,不需要提前预知JSON结构,支持任意层级嵌套。
实现代码
using Newtonsoft.Json.Linq; using System.Linq; public static JObject MergeByCustomRule(JObject json1, JObject json2) { // 深拷贝Json1作为结果基底,避免修改原始输入对象 JObject result = (JObject)json1.DeepClone(); MergeNode(result, json2); return result; } private static void MergeNode(JObject targetNode, JObject sourceNode) { // 只遍历目标节点(来自Json1)的现有属性,天然跳过源节点(来自Json2)独有的属性 foreach (var property in targetNode.Properties().ToList()) { // 检查源节点是否存在同名字段 if (sourceNode.TryGetValue(property.Name, out JToken sourceValue)) { // 如果双方都是对象类型,递归合并内部子属性 if (property.Value.Type == JTokenType.Object && sourceValue.Type == JTokenType.Object) { MergeNode((JObject)property.Value, (JObject)sourceValue); } // 其他类型(值类型、数组等)直接用源节点的值覆盖 else { property.Value = sourceValue; } } } }
调用方式
// 解析输入JSON JObject j1 = JObject.Parse(json1Text); JObject j2 = JObject.Parse(json2Text); // 执行合并 JObject mergedResult = MergeByCustomRule(j1, j2); // 输出结果字符串 string output = mergedResult.ToString();
说明
- 嵌套对象会自动递归合并,保留Json1独有的子属性,覆盖共有子属性,和示例预期完全一致
- 默认对数组类型做整体覆盖,如果需要按索引合并、去重合并等自定义逻辑,可在类型判断分支中扩展对应处理
- 全程不会引入Json2中独有的任何层级的属性,完全符合规则要求
内容的提问来源于stack exchange,提问作者Edoardo
相关产品推荐
相关产品推荐

