In this article, we will be learning how to compare two JSON objects in C#.

To download the source code for this article, you can visit our GitHub repository.

Let’s dive in.

Data Preparation

For this article, we will be using a simple console application. Let’s create the console application and then install the Json.NET library by running the command: 

Install-Package Newtonsoft.Json

Json.Net is rich in functionalities to ease the manipulation of JSON objects in C#, we can also use it to serialize objects or to iterate over JSON objects

Having set up the application, let’s add a new TestData class:

public class TestData
{
    public string GeneratePlainJsonString()
    {
        const string jsonString = $$"""
            {
              "name": "Sporty Ride",
              "make": "Toyota",
              "model": "Supra"
            }
            """ ;

        return jsonString;
    }

    public string GenerateNestedJsonString()
    {
        const string jsonString = $$"""
            {
              "name": "Sporty Ride",
              "make": "Toyota",
              "model": "Supra",
              "price": {
                "amount": 40000.00,
                "currency": "USD"
              }
            }
            """ ;

        return jsonString;
    }
}

The two methods return two JSON strings, which we will be comparing throughout this article.

Now that we have all the data we need set up, let’s look at how we can compare two JSON objects.

Comparing JSON Objects Using Json.NET

Some of the approaches we are going to look at when comparing JSON objects are:

  • Using the JToken.DeepEquals method
  • Comparing deserialized objects
  • Using Json.NET with LINQ

That said, let’s create a new JsonComparison class:

public class JsonComparison
{
    public string PlainJsonString { get; set; }
    public string SecondPlainJsonString { get; set; }
    public string NestedJsonString { get; set; }

    public JsonComparison()
    {
        InitializeData();
    }

    public void InitializeData()
    {
        var testData = new TestData();
        PlainJsonString = testData.GeneratePlainJsonString();
        SecondPlainJsonString = testData.GeneratePlainJsonString();
        NestedJsonString = testData.GenerateNestedJsonString();
    }
}

The class has one InitializeData() method, which initializes the three public properties of the class. We will be using this class to discuss the different approaches to comparing JSON objects.

Let’s proceed to look at the first approach.

Using JToken.DeepEquals Method

The JToken.DeepEquals method is part of the Json.NET namespace. We use it when comparing two JSON objects, including the deeply nested objects. Using this method, we pass two JToken objects as parameters. If the two objects are equal, the method returns true, otherwise, it returns false. With this brief explanation, let’s see how we can use this method to compare two JSON objects.

In our JsonComparison class, let’s add a new CompareJsonObjectsUsingDeepEquals() method:

public Dictionary<string, string> CompareJsonObjectsUsingDeepEquals()
{
    var result = new Dictionary<string, string>();
    var plainJsonObject = JToken.Parse(PlainJsonString);
    var secondJsonObject = JToken.Parse(SecondPlainJsonString);
    var nestedJsonObject = JToken.Parse(NestedJsonString);

    var arePlainObjectsEqual = JToken.DeepEquals(plainJsonObject, secondJsonObject);
    var isPlainAndNestedObjectEqual = JToken.DeepEquals(secondJsonObject, nestedJsonObject);
    
    ...
}

We first initialize an empty dictionary that takes string key-value pairs. Then, we convert our JSON strings to JToken objects using the JToken.Parse method. After that, we use the JToken.DeepEquals method to compare the JToken objects. We declare two variables arePlainObjectsEqual and isPlainAndNestedObjectEqual which we assign the result of the comparison. The rest of the implementation can be found here.

If we were to print the results to the console, we’d get:

Plain Objects Result: The plain json objects are equal
Nested Objects Resul: The plain and nested json objects not are equal

We expect this result, because PlainJsonString and SecondPlainJsonString properties have the same JSON string. However, the NestedJsonString property has a nested JSON string which is not equal to the SecondPlainJsonString JSON string.

Comparing Deserialized Objects 

Let’s start with the creation of required classes:

public class Car
{
    public string Name { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }
    public Price Price { get; set; }
}

public class Price
{
    public double Amount { get; set; }
    public string Currency { get; set; }
}

Next, we can add a new CompareDeserializedJsonObjects() method to our class:

public Dictionary<string, string> CompareDeserializedJsonObjects()
{
    var result = new Dictionary<string, string>();
    var car1 = JsonConvert.DeserializeObject<Car>(PlainJsonString);
    var car2 = JsonConvert.DeserializeObject<Car>(SecondPlainJsonString);
    var car3 = JsonConvert.DeserializeObject<Car>(NestedJsonString);

    ...
}

This is only the main and important part of the implementation. The rest of the code can be found here.

In this method, we first deserialize the three JSON strings into Car objects. Deserializing the JSON strings produces objects with this same schema.

After deserializing the objects, we use the Equals() method to compare the objects. Before proceeding, let’s modify the Car class by adding this method:

public override bool Equals(object obj)
{
    if (obj == null || GetType() != obj.GetType())
    {
        return false;
    }

    var car = (Car)obj;

    return Name == car.Name && Model == car.Model && Make == car.Make && Price == car.Price;
}

In this case, we override the Object.Equals() method by writing our own custom logic for comparing the objects. If you need more information on overriding the Equals method, you can find it here.

Please note that in this example, we haven’t added an override for the GetHashCode() method. However, it is good practice to always implement it, especially when working with collections of either HashSet or Dictionary types.

The CompareDeserializedJsonObjects() method uses the Equals method which we’ve implemented in the Car class to compare the two deserialized objects.

Printing results of the comparison to the console, we’d get: 

Plain Objects Result: The two deserialized plain json objects are equal
Nested Objects Result: The plain and nested deserialized objects are not equal

Comparing deserialized objects involves a number of steps before finally getting the solution. This could be tedious if we were comparing objects with many fields. Now let’s look at an alternative approach.

Using Json.NET with LINQ To Compare JSON Objects

Let’s start off by adding a new method to the JsonComparison class:

public Dictionary<string, string> CompareJsonObjectsUsingLinq()
{
    var result = new Dictionary<string, string>();
    var car1 = JObject.Parse(PlainJsonString);
    var car2 = JObject.Parse(SecondPlainJsonString);
    var car3 = JObject.Parse(NestedJsonString);

    var arePlainObjectsEqual = car1.Properties().All(p => p.Value.Equals(car2[p.Name]));
    var isPlainAndNestedObjectEqual = car3.Properties().All(p => p.Value.Equals(car1[p.Name]));

    ...
}

In this method, we first convert the JSON strings into JObject objects using JObject.Parse.  Then, we compare the two plain objects using LINQ by iterating through all the properties, checking whether the values of the properties match each property. If the values of the JSON properties are equal, the method returns true, otherwise, it returns false. The rest of the code is in our repository, please check it out.

This approach builds on LINQ functionality, and it’s quite straightforward. In cases where the JSON objects being compared are large, it can still get the job done.

Conclusion

In this article, we have discussed how we can compare two JSON objects in C#. We have looked at three different approaches that can be used when comparing the objects and how we can use each of them. Till next time, keep learning!