October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan NowOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk8 min

Why JSON Array Diffing Is Harder Than It Looks

Index-based JSON array diffs can be structurally correct yet misleading. Learn how RFC 6902 sequencing, LCS alignment, and stable keys change what a diff reports.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A structural diff of two JSON arrays can be perfectly accurate and still tell you the wrong story. Comparing elements by position reports exactly which index changed, but a person looking at a list of customers, products, or settings usually wants to know which records were added, removed, edited, or reordered. Those are different questions, and no JSON parser can answer the second one from the syntax alone. The matching rule, meaning the rule that decides which old element corresponds to which new element, is part of the design of any array diff.

What an array diff actually has to decide

Every array diff makes an implicit claim about identity. When it reports that element 2 changed from one value to another, it has treated whatever sat at position 2 before as the same thing as whatever sits at position 2 now. For a list of numbers or tags, that may be a reasonable assumption. For a list of objects that represent records, it often is not.

As an Amazon Associate I earn from qualifying purchases.

Consider a list of three users, each with an id and a name. A new version of the document inserts a fourth user at the top. Semantically, one thing happened: a user was added. Positionally, every user has moved one slot down, so each index now holds a different record. A diff that matches by index will report that the first three users were modified and a fourth was added at the end. The output is technically a valid description of the array’s structure, but it is a poor description of the data.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

JSON Patch addresses elements by their current index

RFC 6902, JavaScript Object Notation (JSON) Patch, is an IETF Standards Track specification published in April 2013. A JSON Patch document is an array of operation objects. The specification defines six operations: add, remove, replace, move, copy, and test. Each operation names its target with a JSON Pointer, and an element inside an array is addressed by its index at the moment that operation runs.

The specification states the rule plainly: “Operations are applied sequentially in the order they appear in the array.” This sequencing has consequences that are easy to miss when generating patches:

  • An add at an index inserts the value there and shifts the elements at or above that index one position to the right. The specified index cannot exceed the array length, and - means append.
  • A remove deletes the element at its index and shifts later elements one position to the left.
  • A move is defined as a removal at from followed by an addition at path.
  • Any index used later in the same patch refers to the array as it stands after every earlier operation, not the array as it stood in the original document.

Take the array ["A", "B", "C"] at /items. The operations remove /items/0 followed by remove /items/0 produce ["C"], not ["A"]. The second operation removes B, because by then B occupies index 0. A patch generator that computes every index against the original array, rather than the evolving one, will produce a patch that applies without error and yields the wrong result.

Equal values and equal records are different things

Matching is straightforward for primitives. The string "A" in the old array and the string "A" in the new array can reasonably be treated as the same element, and a value comparison is often enough. Objects are different. Two objects parsed separately from two JSON documents are distinct instances in memory, even when every field matches. Reference identity, which asks whether two variables point to the same object, therefore cannot establish that two records are the same logical entity. Nor can it show that they are different entities.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

RFC 6902’s test operation uses logical JSON equality. Two arrays are equal when they have the same number of values and corresponding positions are equal, and object member order is not significant. That is a precise rule for comparing content. It is not a rule for deciding that two objects at different positions represent one customer or one product. A diff engine needs a separate, explicit answer to that second question.

Longest common subsequence helps, but it inherits the matching rule

A common approach is to align the old and new arrays using a longest common subsequence (LCS). LCS finds the largest set of elements that appear in the same relative order in both arrays, and the elements outside that set become insertions and deletions. This is far better than naive index comparison when an array has a single insertion or deletion, because the surrounding elements stay aligned.

LCS, however, is only as good as the equality test it is given. If that test is strict equality on values, then changed records never match, because any edit to a field makes the object unequal to its old version. If the test is identity of separately parsed objects, nothing matches at all. The algorithm is correct; the notion of “equal” is the weak point.

The jsondiffpatch library, whose array documentation on its master branch was checked in October 2026, illustrates this directly. It uses LCS, and its default matching relies on JavaScript strict equality. That lets it match primitive values and shared object references, but separately instantiated objects do not match merely because their fields look alike. When no value or reference matches can be found, the documented fallback is positional matching. The practical effect is that an insertion near the start of a list of objects can make many following entries appear modified, because the fallback pairs them by position.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Stable keys make record matching possible, if the key is real

The fix for record-like arrays is to supply a rule that says what identifies an element. The jsondiffpatch documentation describes an objectHash option for this purpose. Its example uses candidate identity fields such as name, id, and _id, with array position as the fallback. That example is a demonstration of the mechanism, not a recommendation that name is generally a safe key. A name can change, and two people can share one.

A key is useful only when it has three properties in your data:

  • Stability: it does not change when the record is edited. A surrogate ID or a primary key usually qualifies; a display name, a slug derived from a title, or a timestamp often does not.
  • Uniqueness within the array: two elements should not share a key. If they do, the matcher must decide which pairs correspond, and a naive matcher may silently pair the wrong ones.
  • Presence: every element should carry the key. Missing keys force a fallback, and the fallback is where noisy output tends to come from.

Schema knowledge is what establishes these properties. A JSON document does not announce that id is a primary key. Someone who knows the application has to say so, and the diff must be configured to use it.

Handling the cases that break a key

Even a well-chosen key needs a plan for the messy cases. A workable design should specify what happens in each of these situations:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Duplicate keys: report them as a data problem, or match by a secondary rule and mark the result as uncertain.
  • Missing keys: decide whether to fall back to value equality, to position, or to treat the element as an unmatched addition or removal. Each choice produces a different report.
  • Several plausible matches: when a removed element and an added element share most of their fields, a heuristic may pair them. Whether that pairing is correct depends on the application, so the rule should be explicit and testable.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Move detection is a representation choice

Without move detection, an element that jumps from the end of a list to the beginning appears as a removal at one place and an addition at another. The jsondiffpatch project documents move detection as a refinement applied after LCS. Its stated benefits are potentially smaller deltas, the ability to report a move instead of a delete and re-insert, and continued nested comparison of moved objects or arrays. These are documented behaviors of that library, not guarantees that every diff implementation provides them.

Move detection also carries a compatibility cost. A delta that expresses a move is only useful to a consumer that understands moves and applies them with the same meaning. A patch that uses RFC 6902’s move operation can be applied by any compliant JSON Patch implementation, but a library-specific delta format may not be. Before choosing move detection, confirm that the reader of the diff supports the representation you produce.

Choosing a matching approach

When two or more approaches are on the table, compare them on the following axes. These are editorial criteria drawn from the semantics of the standard and the documented matching controls of the library. They are not a standardized scoring method.

  • Meaning: Is array order itself significant, as in a ranked list or a sequence of steps? Or are the elements records whose identity should survive reordering?
  • Matching evidence: Does the schema provide stable, unique keys? If not, can you defend value or position matching for this data?
  • Ambiguity: What happens with duplicate values, missing identifiers, or several plausible matches?
  • Patch safety: Are operations computed against the evolving array state, in the order they will be applied?
  • Output goal: Do you need a minimal structural patch that a machine can apply, a human-readable account of what changed, or only a reliable changed or unchanged answer?
  • Cost and complexity: Does identity inference and move detection justify the added code and the extra behavior to test, for this dataset?

A practical sequence for building a diff you can trust

  1. Decide whether each array’s order is meaningful. If it is, a positional diff may be the correct model.
  2. For arrays of records, identify the field that is stable and unique in your data, and confirm it is present on every element.
  3. Configure the matcher to use that field first, and document the fallback for elements that lack it.
  4. Generate any RFC 6902 patch against the array state produced by the preceding operations, and test it by applying the patch to the original document and comparing the result with the new document using the test operation or an equivalent equality check.
  5. Run a set of representative cases through the diff: an insertion at the start, a deletion in the middle, a reordering, a duplicate value, and a record with a missing key. Review whether the output matches what a person would call the change.

The last step is where most noisy diffs are found. A diff that is structurally correct can still mislead, and the only reliable way to notice is to compare its output against the changes a person would describe.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

“

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.