Add path-scoped JSON collection strategies#612
Open
akshat62 wants to merge 1 commit into
Open
Conversation
akshat62
force-pushed
the
akshat62/path-scoped-collection-strategies
branch
from
July 18, 2026 08:18
5499798 to
df7bebd
Compare
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #612 +/- ##
==========================================
- Coverage 95.10% 95.07% -0.04%
==========================================
Files 17 18 +1
Lines 4900 5274 +374
==========================================
+ Hits 4660 5014 +354
- Misses 240 260 +20 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
akshat62
force-pushed
the
akshat62/path-scoped-collection-strategies
branch
2 times, most recently
from
July 18, 2026 09:13
dae5993 to
4016686
Compare
Add an opt-in JSON collection comparison facade with path-scoped identity matching, sorting, filtering, normalization, diagnostics, compatibility boundaries, tests, and documentation.
akshat62
force-pushed
the
akshat62/path-scoped-collection-strategies
branch
from
July 18, 2026 10:08
067b7a2 to
a5faa5d
Compare
akshat62
marked this pull request as ready for review
July 18, 2026 10:15
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem statement
DeepDiff compares arbitrary Python and JSON-like structures, but nested API collections are often unordered and keyed by business identity rather than list position. Positional comparison can create cascading false positives when records are inserted, removed, or reordered.
This PR adds an opt-in, reusable normalization layer for declaring collection-specific semantics without changing existing
DeepDiffbehavior.Proposed solution
The PR introduces
DeepJSONDiffandCollectionStrategy. Both inputs are converted into canonical caller-isolated views, then compared by the existingDeepDiffengine.The existing
DeepDiffconstructor and comparison semantics remain unchanged.Selector semantics
Supported selectors include:
[*]matches exactly one array index..*matches exactly one object key.prioritywins.JSON object keys are expected to be strings. Diagnostic paths use the same quoted-key syntax and can be reused as selectors.
Collection behavior
Identity matching
match_bysupports single, composite, and nested fields. Identity values must resolve after normalization to finite JSON scalars:None, booleans, integers, finite floats, or strings.Identity labels use canonical type-preserving encoding, so integer
1, float1.0, and string"1"remain distinct and composite identities cannot collide through delimiter characters.Filtering, normalization, sorting, and exclusion
Filters and normalizers receive defensive copies and may mutate them without modifying caller-owned payloads. Copies are created only when callbacks are configured.
Processing order is:
Identity and sort fields may therefore be excluded from the compared record while still controlling matching or ordering.
sort_byprovides a total, type-stable order for JSON-compatible values. Integers and floats remain distinct. Finite values, infinities, and NaN values have deterministic positions without heterogeneous comparison failures.Structured sort keys are restricted to JSON lists and mappings with string keys. Unsupported values are rejected instead of being ordered through unstable
repr()output.Order-insensitive scalar arrays
compare_as_set=Trueperforms multiset/bag comparison:match_byorsort_by.Missing and duplicate identities
Missing identity policies:
fallback: retain records in an ordered fallback collection;exclude: omit them;error: raiseIdentityExtractionErrorwith input side and path context.Duplicate policies:
error: raiseDuplicateIdentityError;group: retain every record under the identity and optionally order the group withsort_by.Enum members and string values are accepted.
Diagnostics
get_stats()separates diagnostics by input side:Each entry reports the selected strategy, input item count, filtered count, missing-identity count, and duplicate-group count. Separating sides prevents unrelated parent records from being conflated after parent reordering.
DeepDiff keyword compatibility
Identity matching changes selected arrays into canonical mappings. Options whose behavior depends on caller-visible paths, object paths, or iterable positions are rejected instead of being interpreted against a different structure:
include_pathsexclude_pathsexclude_regex_pathsignore_order_funciterable_compare_funccustom_operatorsexclude_obj_callbackexclude_obj_callback_strictOther keyword arguments are forwarded to the underlying
DeepDiffinstance.Result interface
DeepJSONDiffis a composition-based facade rather than a completeDeepDiffsubclass. It implements the read-onlyMappinginterface, delegatesto_dict()andto_json(), and exposes the underlying result throughresult.diff.Backward compatibility
The feature is fully opt-in:
DeepDiffbehavior is unchanged;DeepJSONDiff;Files changed
deepdiff/json_diff.py— facade, strategy model, selector parsing, canonicalization, identity matching, sorting, policies, diagnostics, and compatibility boundaries.deepdiff/__init__.py— public exports.tests/test_json_diff.py— primary functional, regression, and edge-case coverage.tests/test_json_diff_merge_contracts.py— final sorting/exclusion and callback-compatibility contract tests.docs/json_collection_strategies.rst— public behavior and API documentation.deepdiff/docstrings/index.rst— documentation navigation and unreleased note.No custom GitHub Actions workflow is included.
Validation performed
The implementation is validated across Python 3.10–3.14 and includes focused tests for:
Scope and limitations
This PR provides deterministic exact reconciliation. It does not infer business identity or perform fuzzy matching. The selector grammar is intentionally smaller than full JSONPath. Relative identity and sort fields use dotted extraction and numeric list indexes.
For identity-matched collections, result paths contain canonical identity keys rather than unstable original list indexes.