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"
]
}
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.
Compare JSON in Unit Test
If you want to compare JSON in C# Unit Test, you can first install NuGet Package "FluentAssertions.Json" and then simply use C# code as below example
using FluentAssertions;
using FluentAssertions.Json;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
[TestFixture]
public class JsonTests
{
[Test]
public void JsonObject_ShouldBeEqualAsExpected()
{
JToken expected = JToken.Parse(@"{ ""Name"": ""Hello"", ""objectId"": ""4ea9b00b-d601-44af-a990-3034af18fdb1%>"" }");
JToken actual = JToken.Parse(@"{ ""Name"": ""World"", ""objectId"": ""4ea9b00b-d601-44af-a990-3034af18fdb1%>"" }");
actual.Should().BeEquivalentTo(expected);
// you will get Test will fail with output as Difference.
}
}
That should Help.
You may also like to read:
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?