In this article, I have mentioned how we can compare JSON objects in C# and get difference using console application example.

To begin with, we will need to create a new console application project in Visual Studio, I am using VS 2022 with .NET Core 5, you can also use .NET Core 6 or previous versions.

Once you have create the C# console application, you will need to install jsondiffpatch.net Nuget package, which we will use to get JSON difference in C#

Install-Package JsonDiffPatch.Net

Once you have installed above NuGet package, we can simply Compare JSON as below

using JsonDiffPatchDotNet;
using Newtonsoft.Json.Linq;
using System;

namespace JSONCompareCsharp
{
    public class Program
    {
        static void Main(string[] args)
        {
            string original = @"{ ""Name"": ""Vikas"", ""objectId"": ""4ea9b00b-d601-44af-a990-3034af18fdb1%>"" }";
            string duplicate = @"{ ""Name"": ""Vikram"", ""objectId"": ""4ea9b00b-d601-44af-a990-3034af18fdb1%>"" }";

            var jdp = new JsonDiffPatch();
            var left = JToken.Parse(original);
            var right = JToken.Parse(duplicate);

            JToken patch = jdp.Diff(left, right);

            Console.WriteLine(patch.ToString());

        }
    }
}

This will be give output as below

{
  "Name": [
    "Vikas",
    "Vikram"
  ]
}

json-compare-C#

In the above code, we have created 2 JSON strings and used JSONDiffPatch() to get patch, which shows difference object with values.

Using Custom Function to get JSON difference in C#

You can also create a custom function using Newtonsoft.JSON in C# to compare JSON objects and return difference.

Here is the complete C# code example, with the output:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Text;

namespace JSONCompareCsharp
{
    public class Program
    {
        static void Main(string[] args)
        {
            string original = @"{ ""Name"": ""Vikas"", ""objectId"": ""4ea9b00b-d601-44af-a990-3034af18fdb1%>"", ""id"":5 }";
            string duplicate = @"{ ""Name"": ""Vikram"", ""objectId"": ""4ea9b00b-d601-44af-a990-3034af18fdb1%>"",""id"":6 }";

            JObject sourceJObject = JsonConvert.DeserializeObject<JObject>(original);
            JObject targetJObject = JsonConvert.DeserializeObject<JObject>(duplicate);

            Console.WriteLine(CompareObjects(sourceJObject, targetJObject));


        }

        /// <summary>
        /// Deep compare two NewtonSoft JObjects. If they don't match, returns text diffs
        /// </summary>
        /// <param name="source">The expected results</param>
        /// <param name="target">The actual results</param>
        /// <returns>Text string</returns>
        private static StringBuilder CompareObjects(JObject source, JObject target)
        {
            StringBuilder returnString = new StringBuilder();
            foreach (KeyValuePair<string, JToken> sourcePair in source)
            {
                if (sourcePair.Value.Type == JTokenType.Object)
                {
                    if (target.GetValue(sourcePair.Key) == null)
                    {
                        returnString.Append("Key " + sourcePair.Key
                                            + " not found" + Environment.NewLine);
                    }
                    else if (target.GetValue(sourcePair.Key).Type != JTokenType.Object)
                    {
                        returnString.Append("Key " + sourcePair.Key
                                            + " is not an object in target" + Environment.NewLine);
                    }
                    else
                    {
                        returnString.Append(CompareObjects(sourcePair.Value.ToObject<JObject>(),
                            target.GetValue(sourcePair.Key).ToObject<JObject>()));
                    }
                }
                else if (sourcePair.Value.Type == JTokenType.Array)
                {
                    if (target.GetValue(sourcePair.Key) == null)
                    {
                        returnString.Append("Key " + sourcePair.Key
                                            + " not found" + Environment.NewLine);
                    }
                    else
                    {
                        returnString.Append(CompareArrays(sourcePair.Value.ToObject<JArray>(),
                            target.GetValue(sourcePair.Key).ToObject<JArray>(), sourcePair.Key));
                    }
                }
                else
                {
                    JToken expected = sourcePair.Value;
                    var actual = target.SelectToken(sourcePair.Key);
                    if (actual == null)
                    {
                        returnString.Append("Key " + sourcePair.Key
                                            + " not found" + Environment.NewLine);
                    }
                    else
                    {
                        if (!JToken.DeepEquals(expected, actual))
                        {
                            returnString.Append("Key " + sourcePair.Key + ": "
                                                + sourcePair.Value + " !=  "
                                                + target.Property(sourcePair.Key).Value
                                                + Environment.NewLine);
                        }
                    }
                }
            }
            return returnString;
        }

        /// <summary>
        /// Deep compare two NewtonSoft JArrays. If they don't match, returns text diffs
        /// </summary>
        /// <param name="source">The expected results</param>
        /// <param name="target">The actual results</param>
        /// <param name="arrayName">The name of the array to use in the text diff</param>
        /// <returns>Text string</returns>
        private static StringBuilder CompareArrays(JArray source, JArray target, string arrayName = "")
        {
            var returnString = new StringBuilder();
            for (var index = 0; index < source.Count; index++)
            {

                var expected = source[index];
                if (expected.Type == JTokenType.Object)
                {
                    var actual = (index >= target.Count) ? new JObject() : target[index];
                    returnString.Append(CompareObjects(expected.ToObject<JObject>(),
                        actual.ToObject<JObject>()));
                }
                else
                {

                    var actual = (index >= target.Count) ? "" : target[index];
                    if (!JToken.DeepEquals(expected, actual))
                    {
                        if (String.IsNullOrEmpty(arrayName))
                        {
                            returnString.Append("Index " + index + ": " + expected
                                                + " != " + actual + Environment.NewLine);
                        }
                        else
                        {
                            returnString.Append("Key " + arrayName
                                                + "[" + index + "]: " + expected
                                                + " != " + actual + Environment.NewLine);
                        }
                    }
                }
            }
            return returnString;
        }
    }
}

The above code will give output as below:

Key Name: Vikas !=  Vikram
Key id: 5 !=  6

We have 2 methods (CompareObjects, CompareArrays) above which will through source and target key-pair objects.

If there is any difference between values, we are printing the property names and values.

You may also like to read:

Create text file in C#

SingleOrDefault vs FirstOrDefault in C#

Remove last character from string in C#

What is Console.Log Equivalent in C#?

Check Visual Studio version OR VS Code version

How to change Python version in Visual Studio (VS) Code?

How to Select LAST N Row in SQL Server

How to define C# multiline string literal?

What is Eclipse Comment shortcut?