You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在C#中计算两个JSON对象的差异并生成指定结构的结果JSON

在C#中计算两个JSON对象的差异并生成指定结构的结果JSON

我明白你想要的是和原JSON结构对齐的差异结果,而不是JsonPatch那种操作指令式的输出。用Json.NET(Newtonsoft.Json)来实现这个需求会很灵活,下面我给你写个实用的递归对比方法,完全符合你的要求:

实现思路

核心逻辑是递归遍历新旧两个JSON对象的所有属性,按照规则生成差异结构:

  • 新增属性:原对象没有、新对象有的,直接保留新对象的值
  • 删除属性:原对象有、新对象没有的,设为空字符串
  • 修改属性:两者都有但值不同的,保留新对象的值;如果是嵌套对象,只保留嵌套结构里有变化的属性
  • 无变化的属性:直接忽略,不加入结果

代码实现

首先确保你已经安装了Newtonsoft.Json NuGet包,然后可以用下面的代码:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public static class JsonDiffHelper
{
    public static JObject GenerateStructuredDiff(JObject oldObj, JObject newObj)
    {
        var diffObj = new JObject();

        // 遍历新对象的所有属性,处理新增和修改的情况
        foreach (var prop in newObj.Properties())
        {
            var oldProp = oldObj.Property(prop.Name);
            if (oldProp == null)
            {
                // 新增属性:直接加入结果
                diffObj.Add(prop.Name, prop.Value.DeepClone());
            }
            else
            {
                if (prop.Value.Type == JTokenType.Object && oldProp.Value.Type == JTokenType.Object)
                {
                    // 嵌套对象:递归处理差异
                    var nestedDiff = GenerateStructuredDiff((JObject)oldProp.Value, (JObject)prop.Value);
                    if (nestedDiff.HasValues)
                    {
                        diffObj.Add(prop.Name, nestedDiff);
                    }
                }
                else if (!JToken.DeepEquals(prop.Value, oldProp.Value))
                {
                    // 值不同的属性:保留新值
                    diffObj.Add(prop.Name, prop.Value.DeepClone());
                }
            }
        }

        // 遍历原对象的属性,处理删除的情况
        foreach (var prop in oldObj.Properties())
        {
            if (newObj.Property(prop.Name) == null)
            {
                // 删除属性:设为空字符串
                diffObj.Add(prop.Name, string.Empty);
            }
        }

        return diffObj;
    }
}

// 测试示例
class Program
{
    static void Main()
    {
        string obj1Json = @"
        {
            ""id"": ""94774"",
            ""name"": ""testName"",
            ""colour"": ""red"",
            ""date"": {
                ""year"": 2021,
                ""month"": 10,
                ""day"": 21
            }
        }";

        string obj2Json = @"
        {
            ""id"": ""86970"",
            ""name"": ""testName"",
            ""foo"": ""bar"",
            ""date"": {
                ""year"": 2022,
                ""month"": 10,
                ""day"": 21
            }
        }";

        JObject oldObj = JObject.Parse(obj1Json);
        JObject newObj = JObject.Parse(obj2Json);

        JObject diffResult = JsonDiffHelper.GenerateStructuredDiff(oldObj, newObj);
        Console.WriteLine(diffResult.ToString(Formatting.Indented));
    }
}

运行结果

执行上面的代码,输出的结果和你期望的完全一致:

{
  "id": "86970",
  "foo": "bar",
  "date": {
    "year": 2022
  },
  "colour": ""
}

补充说明

  • 如果你的项目用的是System.Text.Json,也可以用类似的递归逻辑,通过JsonElement来遍历属性,只是API会略有不同
  • 这个方法支持多层嵌套的JSON结构,不管嵌套多少层,都会只保留有变化的部分
  • 对于数组类型的属性,当前代码会直接对比整个数组是否相等,如果需要更细粒度的数组差异,可以在方法里添加数组的处理逻辑

备注:内容来源于stack exchange,提问作者Nick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 10:17:58