you might want to look at jsondiffpatch (disclaimer: I'm the author),

you can try it online here, just some highlights:

  • a smart array diff (uses LCS to detect adds/removes, and finds item moved in arrays)
  • it's pretty customizable, you can even write plugins to change any part of diff/patch mechanism
  • if 2 long strings are found anywhere in the graph, it will use the Neil Fraser's lib you mention internally to get a text unidiff
  • multiple formatters, html (the one used at the online demo), console, annotated, and now jsonpatch (RFC6902)

this should work for diffing/patching any 2 objects, framework agnostic, if ExtJS defines special private properties on your objects, you can ignore them specifying a propertyFilter

Answer from Benja on Stack Overflow
🌐
GitHub
github.com › benjamine › jsondiffpatch
GitHub - benjamine/jsondiffpatch: Diff & patch JavaScript objects · GitHub
diffMatchPatch: diff_match_patch, // default 60, minimum string length (left and right sides) to use text diff algorithm: google-diff-match-patch minLength: 60, }, propertyFilter: function (name, context) { /* this optional function can be specified to ignore object properties (eg. volatile data) name: property name, present in either context.left or context.right objects context: the diff context (has context.left and context.right objects) */ return name.slice(0, 1) !== '$'; }, cloneDiffValues: false /* default false. if true, values in the obtained delta will be cloned (using jsondiffpatch.clone by default), to ensure delta keeps no references to left or right objects. this becomes useful if you're diffing and patching the same objects multiple times without serializing deltas.
Author   benjamine
🌐
Jsondiffpatch
jsondiffpatch.com
JsonDiffPatch
JsonDiffPatch is a free online json diff tool and npm library to compare json and get a json diff.
🌐
npm
npmjs.com › package › json-diff-patch
json-diff-patch - npm
Library to generate JSON Patches in JavaScript, from two differing json obejcts.
      » npm install json-diff-patch
    
Published   Feb 07, 2013
Version   0.0.1
Author   Adam Griffiths
🌐
GitHub
github.com › wbish › jsondiffpatch.net
GitHub - wbish/jsondiffpatch.net: JSON object diffs and reversible patching (jsondiffpatch compatible) · GitHub
JsonDiffPatch.Net is designed to handle complex diffs by producing a compact diff object with enough information to patch and unpatch relevant JSON objects.
Author   wbish
🌐
npm
npmjs.com › package › jsondiffpatch
jsondiffpatch - npm
JSON diff & patch (object and array diff, text diff, multiple output formats). Latest version: 0.7.3, last published: a year ago. Start using jsondiffpatch in your project by running `npm i jsondiffpatch`. There are 587 other projects in the npm registry using jsondiffpatch.
      » npm install jsondiffpatch
    
Published   Mar 31, 2025
Version   0.7.3
Author   Benjamin Eidelman
🌐
NuGet
nuget.org › packages › JsonDiffPatch.Net
NuGet Gallery | JsonDiffPatch.Net 2.5.0
JSON object diffs and reversible patching · Compatible target framework(s) Included target framework(s) (in package) Learn more about Target Frameworks and .NET Standard.
🌐
crates.io
crates.io › crates › jsondiffpatch
jsondiffpatch - crates.io: Rust Package Registry
A Rust implementation of JSON diff & patch functionality, providing object and array diff, text diff, and multiple output formats.
🌐
GitHub
github.com › mcintyre321 › JsonDiffPatch
GitHub - mcintyre321/JsonDiffPatch
var patchDoc = new PatchDocument( new Operation[] { new TestOperation() {Path = new JsonPointer("/a/b/c"), Value = new JValue("foo")}, new RemoveOperation() {Path = new JsonPointer("/a/b/c") }, new AddOperation() {Path = new JsonPointer("/a/b/c"), Value = new JArray(new JValue("foo"), new JValue("bar"))}, new ReplaceOperation() {Path = new JsonPointer("/a/b/c"), Value = new JValue(42)}, new MoveOperation() {FromPath = new JsonPointer("/a/b/c"), Path = new JsonPointer("/a/b/d") }, new CopyOperation() {FromPath = new JsonPointer("/a/b/d"), Path = new JsonPointer("/a/b/e") }, });
Starred by 54 users
Forked by 24 users
Languages   C#
Find elsewhere
🌐
GitHub
github.com › weichch › system-text-json-jsondiffpatch
GitHub - weichch/system-text-json-jsondiffpatch: High-performance, low-allocating JSON object diff and patch extension for System.Text.Json. Support generating patch document in RFC 6902 JSON Patch format. · GitHub
High-performance, low-allocating JSON object diff and patch extension for System.Text.Json. Support generating patch document in RFC 6902 JSON Patch format. - weichch/system-text-json-jsondiffpatch
Author   weichch
🌐
GitHub
github.com › soraxas › jsondiffpatch
GitHub - soraxas/jsondiffpatch: JSON diff & patch
A Rust implementation of JSON diff & patch functionality, providing object and array diff, text diff, and multiple output formats.
Author   soraxas
🌐
GitHub
github.com › josephburnett › jd
GitHub - josephburnett/jd: JSON diff and patch · GitHub
Usage: jd [OPTION]... FILE1 [FILE2] Diff and patch JSON files. Prints the diff of FILE1 and FILE2 to STDOUT. When FILE2 is omitted the second input is read from STDIN. When patching (-p) FILE1 is a diff.
Author   josephburnett
Top answer
1 of 1
2

Yes, I think you are on the right track.

JSON-Patch (RFC6902), at its core, tries to solve the very problem you facing here: partial updates. JSON Patch offers an atomic update request that patches your JSON using a series of "add", "remove", "replace", "move" and "copy" operations. To quote one of the authors of the JSON Patch RFC, Mark Nottingham (IETF):

This has a bunch of advantages. Since it’s a generic format, you can write server- and client-side code once, and share it among a number of applications. You can do QA once, and make sure you get it right. Furthermore, your API will become less complex, because it has less URI conventions, leading to more flexibility and making it easier to approach for new developers. Using this approach will also make caches operate more correctly; since modifications to a resource will “travel” through its URL, rather than some other one, the right stored responses will get invalidated.

ASP.NET Core offers JSON-Patch support. JSON Patch can be added by installing Microsoft JSON Patch library (Nuget) from the Package Manager console:

CopyInstall-Package Microsoft.AspNetCore.JsonPatch

Then you apply patches using the JsonPatchDocument class and its methods like ApplyTo, Add, Copy, Move, Remove, Replace.

In an ASP.NET Core Web API context, we can also make use of the Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet package.

And then use the PUT and PATCH methods to update an existing resource with JSON Patch operations.

This MSDN article has some good explanations and a sample project.


In a JavaScript/Node.js project, you could also choose from a larger list of JS implementations, notably fast-json-patch.

Resources:

  • Official JSON Patch documentation.
  • .NET CORE Tutorials: JSON Patch With ASP.NET Core

Side note: Another option is JSON Merge Patch (RFC7396), which can be used to send partial updates as well but works more like an actual diff/patch that simply contains the changes instead of using mutating operations. In this respect, JSON Merge Patch is simpler but more limited than JSON Patch, e.g. you cannot set a key to null (since null means remove), merging only works with objects {..}, arrays [..] can only be replaced as a whole, and merging never fails, could cause side-effects and is therefore not transactional. This renders Merge Patch (overly) simplistic and impractical for certain real-world applications. There are more related projects named like JSON-Diffpatch, etc that take similar approaches. Arguably, JSON-Patch is more flexible but both have advantages and disadvantages.

🌐
NuGet
nuget.org › packages › JsonDiffPatch
NuGet Gallery | JsonDiffPatch 2.0.61
Library for diffing and RFC 6902 patching json.net json objects - forked from Tavis.JsonPatch, with an addition of json diff code by Ian Mercer, with additional partial array LCS diff by JC Dickinson
🌐
Go Packages
pkg.go.dev › github.com › wI2L › jsondiff
jsondiff package - github.com/wI2L/jsondiff - Go Packages
This produce one or more operations for each difference found. On the other hand, in certain situations, it might be beneficial to replace a set of operations representing several changes inside a JSON node by a single replace operation targeting the parent node, in order to reduce the "size" of the patch (the length in bytes of the JSON representation of the patch).
🌐
Terminusdb
terminusdb.org › docs › json-diff-and-patch
JSON Diff and Patch with TerminusDB
Have a token and your username that can be found in the profile section to use with the below example where the cloud diff and patch operations are used. ... TOKEN=01234567-0123-0123-0123... DFRNT_USER=00000000-0000-0000... curl -H "Authorization: Token $TOKEN" -X POST -H "Content-Type: application/json" "https://dfrnt.com/api/hosted/${DFRNT_USER}/api/diff" -d \ '{ "before" : { "asdf" : "foo", "fdsa" : "bar"}, "after" : { "asdf" : "bar", "fdsa" : "bar"}, "keep" : { "fdsa" : true}}'
🌐
GitHub
github.com › apack1001 › json-diff-patch
GitHub - apack1001/json-diff-patch: a python clone of benjamine/jsondiffpatch
Calculate difference between two JSON documents and output it in JSON patch format.
Starred by 6 users
Forked by 2 users
Languages   Python
🌐
JSON for Modern C++
json.nlohmann.me › features › json_patch
JSON Patch and Diff - JSON for Modern C++
With the patch function, a JSON Patch is applied to the current JSON value by executing all operations from the patch.
🌐
Rust
docs.rs › json-patch › latest › json_patch › fn.diff.html
diff in json_patch - Rust
#[macro_use] use json_patch::{Patch, patch, diff}; use serde_json::{json, from_value}; let left = json!({ "title": "Goodbye!", "author" : { "givenName" : "John", "familyName" : "Doe" }, "tags":[ "example", "sample" ], "content": "This will be unchanged" }); let right = json!({ "title": "Hello!", "author" : { "givenName" : "John" }, "tags": [ "example" ], "content": "This will be unchanged", "phoneNumber": "+01-123-456-7890" }); let p = diff(&left, &right); assert_eq!(p, from_value::<Patch>(json!([ { "op": "replace", "path": "/title", "value": "Hello!"