Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect differences between two json files in c#

Tags:

json

c#

For example, if I have the following json texts:

 object1{
     field1: value1;
     field2: value2;
     field3: value3;
 }

 object1{
     field1: value1;
     field2: newvalue2;
     field3: value3;
 }

I need something in c# that reads that files and shows the difference. i.e. it can return the following object:

differences {
    object1: { field: field2, old_value: value2, new_value: newvalue2}
}

Is there some API or suggestions to do this?

like image 699
Tony Avatar asked Jun 14 '12 13:06

Tony


People also ask

How do you find the difference between two JSON files?

Comparing Json: Comparing json is quite simple, we can use '==' operator, Note: '==' and 'is' operator are not same, '==' operator is use to check equality of values , whereas 'is' operator is used to check reference equality, hence one should use '==' operator, 'is' operator will not give expected result.

How can I find the difference between two JSON files in C#?

var result = diffObj. Diff(json1, json2); Other important thing to mention is that the Diff method can also receive as parameters JTokens (and, in this case, it returns a JToken with the diff), which might be useful if you are working with Json.net. After getting the diff JSON, we can simply print it to the console.

Can we compare two JSON files?

You can also directly compare two JSON files by specifying their urls in the GET parameters url1 and url2. Then you can visualize the differences between the two JSON documents. It highlights the elements which are different: Different value between the two JSON: highlight in red color.


2 Answers

I recommend you use Weakly-Typed JSON Serialization and write a routine that uses JsonObject like this:

String JsonDifferenceReport(String objectName,
                            JsonObject first,
                            JsonObject second)
{
  if(String.IsNullOrEmpty(objectName))
    throw new ArgumentNullException("objectName");
  if(null==first)
    throw new ArgumentNullException("first");
  if(null==second)
    throw new ArgumentNullException("second");
  List<String> allKeys = new List<String>();
  foreach(String key in first.Keys)
    if (!allKeys.Any(X => X.Equals(key))) allKeys.Add(key);
  foreach(String key in second.Keys)
    if (!allKeys.Any(X => X.Equals(key))) allKeys.Add(key);
  String results = String.Empty;
  foreach(String key in allKeys)
  {
    JsonValue v1 = first[key];
    JsonValue v1 = second[key];
    if (((null==v1) != (null==v2)) || !v1.Equals(v2))
    {
      if(String.IsNullOrEmpty(results))
      {
         results = "differences: {\n";
      }
      results += "\t" + objectName + ": {\n";
      results += "\t\tfield: " + key + ",\n";
      results += "\t\toldvalue: " + (null==v1)? "null" : v1.ToString() + ",\n";
      results += "\t\tnewvalue: " + (null==v2)? "null" : v2.ToString() + "\n";
      results += "\t}\n";
    }
  }
  if(!String.IsNullOrEmpty(results))
  {
    results += "}\n";
  }
  return results;
}

Your choice whether to get reports recursively inside JsonValue v1 and v2, instead of just using their string representation as I did here.

If you wanted to go recursive, it might change the above like this:

  if ((null==v1) || (v1.JsonType == JsonType.JsonPrimitive)
   || (null==v2) || (v2.JsonType == JsonType.JsonPrimitive))
  {
    results += "\t\tfield: " + key + ",\n";
    results += "\t\toldvalue: " + (null==v1) ? "null" : v1.ToString() + ",\n";
    results += "\t\tnewvalue: " + (null==v2) ? "null" : v2.ToString() + "\n";
  }
  else
  {
    results + JsonDifferenceReport(key, v1, v2);
  }

-Jesse

like image 79
Jesse Chisholm Avatar answered Sep 16 '22 12:09

Jesse Chisholm


I've constructed my own method for Json comparison. It uses Newtonsoft.Json.Linq.

    public static JObject FindDiff(this JToken Current, JToken Model)
    {
        var diff = new JObject();
        if (JToken.DeepEquals(Current, Model)) return diff;

        switch(Current.Type)
        {
            case JTokenType.Object:
                {
                    var current = Current as JObject;
                    var model = Model as JObject;
                    var addedKeys = current.Properties().Select(c => c.Name).Except(model.Properties().Select(c => c.Name));
                    var removedKeys = model.Properties().Select(c => c.Name).Except(current.Properties().Select(c => c.Name));
                    var unchangedKeys = current.Properties().Where(c => JToken.DeepEquals(c.Value, Model[c.Name])).Select(c => c.Name);
                    foreach (var k in addedKeys)
                    {
                        diff[k] = new JObject
                        {
                            ["+"] = Current[k]
                        };
                    }
                    foreach (var k in removedKeys)
                    {
                        diff[k] = new JObject
                        {
                            ["-"] = Model[k]
                        };
                    }
                    var potentiallyModifiedKeys = current.Properties().Select(c => c.Name).Except(addedKeys).Except(unchangedKeys);
                    foreach (var k in potentiallyModifiedKeys)
                    {
                        diff[k] = FindDiff(current[k], model[k]);
                    }
                }
                break;
            case JTokenType.Array:
                {
                    var current = Current as JArray;
                    var model = Model as JArray;
                    diff["+"] = new JArray(current.Except(model));
                    diff["-"] = new JArray(model.Except(current));
                }
                break;
            default:
                diff["+"] = Current;
                diff["-"] = Model;
                break;
        }

        return diff;
    }
like image 38
Dzmitry Paliakou Avatar answered Sep 17 '22 12:09

Dzmitry Paliakou