JSON object diffs and reversible patching (jsondiffpatch compatible)
Go to file
William Bishop c2b2458823 Update JsonDeltaFormatterUnitTests.cs 2023-01-16 17:02:08 -06:00
Src Update JsonDeltaFormatterUnitTests.cs 2023-01-16 17:02:08 -06:00
.editorconfig Moved editorconfig to root 2020-03-30 14:05:27 -05:00
.gitignore Add JetBrains ignore 2020-09-04 15:08:20 +10:00
LICENSE Initial commit 2016-01-25 18:43:14 -08:00
README.md Corrected google-diff-match-patch link in README.md 2020-04-07 12:09:11 +03:00

README.md

jsondiffpatch.net

Build status NuGet

JSON object diffs and reversible patching (jsondiffpatch compatible)

Installing

Install from jsondiffpatch.net nuget website, or run the following command:

Install-Package JsonDiffPatch.Net

Usage

The library has support for the following 3 operations: Diff, Patch and Unpatch.

Diff

Diff two json objects

  var jdp = new JsonDiffPatch();
  var left = JToken.Parse(@"{ ""key"": false }");
  var right = JToken.Parse(@"{ ""key"": true }");

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

  Console.WriteLine(patch.ToString());

  // Output:
  // {
  //     "key": [false, true]
  // }

Patch

Patch a left object with a patch document

  var jdp = new JsonDiffPatch();
  var left = JToken.Parse(@"{ ""key"": false }");
  var right = JToken.Parse(@"{ ""key"": true }");
  JToken patch = jdp.Diff(left, right);

  var output = jdp.Patch(left, patch);

  Console.WriteLine(output.ToString());

  // Output:
  // {
  //     "key": true
  // }

Unpatch

Unpatch a right object with a patch document

  var jdp = new JsonDiffPatch();
  var left = JToken.Parse(@"{ ""key"": false }");
  var right = JToken.Parse(@"{ ""key"": true }");
  JToken patch = jdp.Diff(left, right);

  var output = jdp.Unpatch(right, patch);

  Console.WriteLine(output.ToString());

  // Output:
  // {
  //     "key": false
  // }

Advanced Usage

JsonDiffPatch.Net is designed to handle complex diffs by producing a compact diff object with enough information to patch and unpatch relevant JSON objects. The following are some of the most common cases you may hit when generating a diff:

  • Adding, Removing a property from an object
  • Changing the property value or even value type
  • Inserting and shifting elements in an array
  • Efficient string diffing using google-diff-match-patch
  • Nested object diffs

The full JSON patch document format is documented at https://github.com/benjamine/jsondiffpatch.

var left =
{
  "id": 100,
  "revision": 5,
  "items": [
    "car",
    "bus"
  ],
  "tagline": "I can't do it. This text is too long for me to handle! Please help me JsonDiffPatch!",
  "author": "wbish"
}

var right =
{
  "id": 100,
  "revision": 6,
  "items": [
    "bike",
    "bus",
    "car"
  ],
  "tagline": "I can do it. This text is not too long. Thanks JsonDiffPatch!",
  "author": {
    "first": "w",
    "last": "bish"
  }
}

var jdp = new JsonDiffPatch();
var output = jdp.Diff(left, right);

// Output:
{
  "revision": [   // Changed the value of a property
    5,            // Old value
    6             // New value
  ],
  "items": {      // Inserted and moved items in an array
    "0": [
      "bike"
    ],
    "_t": "a",
    "_1": [
      "",
      1,
      3
    ]
  },
  "tagline": [    // A long string diff using google-diff-match-patch
    "@@ -2,10 +2,8 @@\n  can\n-'t\n  do \n@@ -23,49 +23,28 @@\n  is \n+not \n too long\n- for me to handle! Please help me\n+. Thanks\n  Jso\n",
    0,
    2
  ],
  "author": [     // Changed the type of the author property from string to object
    "wbish",
    {
      "first": "w",
      "last": "bish"
    }
  ]
}

JSON Patches (RFC 6902)

A diff result can be converted into JSON patches, according to the RFC 6902 spec.

var left = JObject.Parse("{ \"name\": \"Justin\" }");
var right = JObject.Parse("{ \"name\" : \"John\", \"age\": 34 }");
var patch = new JsonDiffPatch().Diff(left, right);
var formatter = new JsonDeltaFormatter();
var operations = formatter.Format(patch);

/*
operations: [
  { "op": "replace", "path": "/name", "value": "John" },
  { "op": "add", "path": "/age", "value": 34 }
]
*/

Attributions