0
# Core Operations
1
2
Primary functions for computing differences and measuring similarity between JSON structures. These form the main public API of the jsondiff library and provide convenient access to the underlying JsonDiffer functionality.
3
4
## Capabilities
5
6
### Difference Computation
7
8
Computes the difference between two JSON structures using a specified JsonDiffer class and returns the diff in the configured format.
9
10
```python { .api }
11
def diff(a, b, fp=None, cls=JsonDiffer, **kwargs):
12
"""
13
Computes the difference between two JSON structures.
14
15
Parameters:
16
- a: The original JSON structure (dict, list, set, tuple, or primitive)
17
- b: The modified JSON structure (dict, list, set, tuple, or primitive)
18
- fp: Optional file pointer to dump the diff to
19
- cls: The JsonDiffer class or subclass to use (default: JsonDiffer)
20
- **kwargs: Additional keyword arguments for JsonDiffer constructor
21
- syntax: 'compact', 'symmetric', 'explicit', 'rightonly' (default: 'compact')
22
- load: bool, auto-load JSON from strings/files (default: False)
23
- dump: bool, auto-dump output to JSON (default: False)
24
- marshal: bool, marshal diffs for safe serialization (default: False)
25
26
Returns:
27
dict: The computed diff structure
28
29
Note: For exclude_paths functionality, use JsonDiffer.diff() method directly
30
"""
31
```
32
33
**Usage Examples:**
34
35
```python
36
from jsondiff import diff, JsonDiffer
37
from jsondiff.symbols import delete, insert
38
39
# Dictionary differences
40
original = {'name': 'Alice', 'age': 30, 'city': 'NYC'}
41
modified = {'name': 'Alice', 'age': 31, 'city': 'Boston', 'country': 'USA'}
42
43
result = diff(original, modified)
44
# Result: {'age': 31, 'city': 'Boston', 'country': 'USA'}
45
46
# With explicit syntax for clarity
47
result = diff(original, modified, syntax='explicit')
48
# Result: {insert: {'country': 'USA'}, update: {'age': 31, 'city': 'Boston'}}
49
50
# List differences
51
list1 = ['apple', 'banana', 'cherry']
52
list2 = ['apple', 'blueberry', 'cherry', 'date']
53
54
result = diff(list1, list2)
55
# Result: {1: 'blueberry', insert: [(3, 'date')]}
56
57
# Set differences
58
set1 = {'red', 'green', 'blue'}
59
set2 = {'red', 'yellow', 'blue'}
60
61
result = diff(set1, set2)
62
# Result: {discard: {'green'}, add: {'yellow'}}
63
64
# Path exclusion (requires JsonDiffer class)
65
data1 = {'user': {'name': 'John', 'age': 25, 'temp_id': 123}}
66
data2 = {'user': {'name': 'John', 'age': 26, 'temp_id': 456}}
67
68
differ = JsonDiffer()
69
result = differ.diff(data1, data2, exclude_paths=['user.temp_id'])
70
# Result: {'user': {'age': 26}}
71
72
# Auto-loading from JSON strings
73
json1 = '{"a": 1, "b": 2}'
74
json2 = '{"a": 1, "b": 3, "c": 4}'
75
76
result = diff(json1, json2, load=True)
77
# Result: {'b': 3, 'c': 4}
78
```
79
80
### Patch Application
81
82
Applies a diff to a JSON structure to produce the modified structure. **Note: The `patch` function is not exported in the main module. Use `JsonDiffer.patch()` method instead.**
83
84
**Usage Examples:**
85
86
```python
87
from jsondiff import diff, JsonDiffer
88
89
# Basic patching using JsonDiffer
90
original = {'name': 'Alice', 'age': 30}
91
modified = {'name': 'Alice', 'age': 31, 'city': 'NYC'}
92
93
# Create diff and apply patch
94
diff_result = diff(original, modified)
95
differ = JsonDiffer()
96
patched = differ.patch(original, diff_result)
97
print(patched) # {'name': 'Alice', 'age': 31, 'city': 'NYC'}
98
99
# List patching
100
list1 = ['a', 'b', 'c']
101
list2 = ['a', 'x', 'c', 'd']
102
103
diff_result = diff(list1, list2)
104
patched = differ.patch(list1, diff_result)
105
print(patched) # ['a', 'x', 'c', 'd']
106
107
# Set patching
108
set1 = {1, 2, 3}
109
set2 = {1, 3, 4, 5}
110
111
diff_result = diff(set1, set2)
112
patched = differ.patch(set1, diff_result)
113
print(patched) # {1, 3, 4, 5}
114
115
# Symmetric syntax with unpatch capability
116
original = {'x': 10, 'y': 20}
117
modified = {'x': 15, 'y': 20, 'z': 30}
118
119
differ = JsonDiffer(syntax='symmetric')
120
diff_result = differ.diff(original, modified)
121
patched = differ.patch(original, diff_result)
122
print(patched) # {'x': 15, 'y': 20, 'z': 30}
123
```
124
125
### Similarity Measurement
126
127
Calculates the similarity score between two JSON structures, returning a float value between 0.0 (completely different) and 1.0 (identical).
128
129
```python { .api }
130
def similarity(a, b, cls=JsonDiffer, **kwargs):
131
"""
132
Calculates the similarity score between two JSON structures.
133
134
Parameters:
135
- a: The first JSON structure
136
- b: The second JSON structure
137
- cls: The JsonDiffer class or subclass to use (default: JsonDiffer)
138
- **kwargs: Additional keyword arguments for JsonDiffer constructor
139
- load: bool, auto-load JSON from strings/files (default: False)
140
141
Returns:
142
float: Similarity score between 0.0 and 1.0
143
"""
144
```
145
146
**Usage Examples:**
147
148
```python
149
from jsondiff import similarity
150
151
# Identical structures
152
data1 = {'a': 1, 'b': 2}
153
data2 = {'a': 1, 'b': 2}
154
score = similarity(data1, data2)
155
print(score) # 1.0
156
157
# Completely different structures
158
data1 = {'a': 1, 'b': 2}
159
data2 = {'x': 10, 'y': 20}
160
score = similarity(data1, data2)
161
print(score) # 0.0
162
163
# Partially similar structures
164
data1 = {'name': 'Alice', 'age': 30, 'city': 'NYC'}
165
data2 = {'name': 'Alice', 'age': 31, 'city': 'Boston'}
166
score = similarity(data1, data2)
167
print(score) # ~0.75 (name matches, age/city partially similar)
168
169
# List similarity
170
list1 = ['a', 'b', 'c', 'd']
171
list2 = ['a', 'x', 'c', 'd']
172
score = similarity(list1, list2)
173
print(score) # ~0.75 (3 out of 4 elements match positions)
174
175
# Set similarity
176
set1 = {1, 2, 3, 4, 5}
177
set2 = {1, 2, 3, 6, 7}
178
score = similarity(set1, set2)
179
print(score) # 0.6 (3 common elements out of 5 total unique)
180
```
181
182
## Error Handling
183
184
The core functions handle various error conditions:
185
186
```python
187
from json import JSONDecodeError
188
from yaml import YAMLError
189
190
# Invalid JSON when load=True
191
try:
192
result = diff('{"invalid": json}', '{"valid": "json"}', load=True)
193
except JSONDecodeError as e:
194
print(f"Invalid JSON: {e}")
195
196
# File not found errors are handled by underlying loaders
197
# ValueError raised for invalid serialization formats
198
```
199
200
## Performance Considerations
201
202
- **Large structures**: The diff algorithm uses dynamic programming for list comparisons
203
- **Deep nesting**: Performance may degrade with very deeply nested structures
204
- **Set operations**: Set diffs are optimized using native set operations
205
- **Memory usage**: Large diffs may consume significant memory, consider streaming for very large datasets