-1

Let's say I have two JSON objects (obj1 and obj2) which follow the same schema:

obj1:
{
  "id": "94774",
  "name": "testName",
  "colour": "red",
  "date": {
    "year": 2021,
    "month": 10,
    "day": 21
  }
}
obj2:
{
  "id": "86970",
  "name": "testName",
  "foo": "bar",
  "date": {
    "year": 2022,
    "month": 10,
    "day": 21
  }
}

I would like to compute the difference between these objects, and have the resulting changes presented in the same schema as the original objects (comments are added for clarity here, and not required in the resulting output):

{
  "id": "86970",  // modified
  "colour": "",   // removed
  "foo": "bar",   // added
  "date": {
    "year": 2022  // modified
  }
}

How would this be done? I have tried using JsonPatchDocument from Microsoft, and that can provide me with the differences between two objects, but I can't get it in the output format I'd like.

I am using C# but would consider any other relevant solutions to this problem.

Edit:

How do you decide which of the two objects is the one to keep its values for building the difference json? - Steve

obj2 is the "newer" object, so the intent is that the elements in obj2 update the elements in obj1.

Have you tried any of the nine answers from Find and return JSON differences using newtonsoft in C#?? E.g. this answer by Amin M shows a diff format that seems to resemble yours. - dbc

No I didn't think of searching StackOverflow before posting this question, thanks for the tip! /sarcasm. This is why people don't like this place. If any of those answers went any way to solving my problem then I wouldn't have posted the question, would I? Also thanks for the -1, super helpful and not toxic at all!

Nick
  • 685
  • 12
  • 27
  • 1
    How do you decide which of the two objects is the one to keep its values for building the difference json? – Steve Jun 20 '23 at 16:02
  • Have you tried any of the nine answers from [Find and return JSON differences using newtonsoft in C#?](https://stackoverflow.com/q/24876082)? E.g. [this answer](https://stackoverflow.com/a/61920404/3744182) by [Amin M](https://stackoverflow.com/users/2663492/amin-m) shows a diff format that seems to resemble yours. – dbc Jun 20 '23 at 16:05
  • What json has to do with it? You just have 2 c# objects and have to figure difference by certain way – Serge Jun 20 '23 at 17:05
  • Or edit your question. Show us the code that creates a difference. We can try to figure how to convert it to a json string. – Serge Jun 20 '23 at 18:31
  • If you already checked and tested the (promising) answers in the question mentioned in the commend of @dbc and that doesn't match your requirements, please tell us, why it doesn't match. After looking at your requirements I would try the top answer https://github.com/wbish/jsondiffpatch.net and the document _Patch()_ method. And maybe provide a [minimal, reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) or even a [dotnetfiddle](https://dotnetfiddle.net) that has running code. – Oliver Jun 21 '23 at 08:38

1 Answers1

1

You could try using JObject and JToken classes from Newtonsoft.Json.

I don't see any part of your code so I've just written a simple c# console app.

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

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 obj1 = JObject.Parse(obj1Json);
        JObject obj2 = JObject.Parse(obj2Json);

        JObject diff = GetJsonDifference(obj1, obj2);

        string diffJson = diff.ToString(Formatting.Indented);
        Console.WriteLine(diffJson);
    }

    static JObject GetJsonDifference(JObject obj1, JObject obj2)
    {
        JObject diff = new JObject();

        foreach (var property in obj1.Properties())
        {
            string propertyName = property.Name;
            JToken obj1Value = property.Value;
            JToken obj2Value = obj2.GetValue(propertyName);

            if (obj2Value == null)
            {
                // Property exists in obj1 but not in obj2, so it was removed
                diff[propertyName] = new JValue(""); // Use an empty string as the marker for removal
            }
            else if (obj1Value.Type == JTokenType.Object && obj2Value.Type == JTokenType.Object)
            {
                // Recursive call to handle nested objects
                JObject nestedDiff = GetJsonDifference((JObject)obj1Value, (JObject)obj2Value);
                if (nestedDiff.HasValues)
                    diff[propertyName] = nestedDiff;
            }
            else if (!JToken.DeepEquals(obj1Value, obj2Value))
            {
                // Property values are different, update it in the diff object
                diff[propertyName] = obj2Value.DeepClone();
            }
        }

        foreach (var property in obj2.Properties())
        {
            string propertyName = property.Name;
            JToken obj1Value = obj1.GetValue(propertyName);
            JToken obj2Value = property.Value;

            if (obj1Value == null)
            {
                // Property exists in obj2 but not in obj1, so it was added
                diff[propertyName] = obj2Value.DeepClone();
            }
        }

        return diff;
    }
}

CherryQuery
  • 428
  • 1
  • 11