0
# Data Context Management
1
2
Classes that wrap data values with their path context information, enabling full path tracking, parent relationships, and automatic ID field generation. These classes maintain the relationship between matched data and their location within the original data structure.
3
4
## Capabilities
5
6
### DatumInContext Class
7
8
The primary data wrapper that represents a value along with its path from a context, functioning as a zipper-like structure with parent pointers.
9
10
```python { .api }
11
class DatumInContext:
12
"""
13
Represents a datum along a path from a context.
14
15
Maintains the relationship between data values and their location
16
within the original data structure, enabling path reconstruction
17
and context navigation.
18
"""
19
20
def __init__(self, value, path=None, context=None):
21
"""
22
Initialize a datum with context.
23
24
Parameters:
25
- value: The actual data value
26
- path: JSONPath object representing path to this datum (default: This())
27
- context: Parent DatumInContext or None for root
28
"""
29
30
@classmethod
31
def wrap(cls, data):
32
"""
33
Wrap data in DatumInContext if not already wrapped.
34
35
Parameters:
36
- data: Data to wrap (any type)
37
38
Returns:
39
DatumInContext: Wrapped data
40
"""
41
42
def in_context(self, context, path):
43
"""
44
Place this datum within another context, extending the path.
45
46
Parameters:
47
- context: Parent context (will be wrapped in DatumInContext)
48
- path: JSONPath representing path from context to this datum
49
50
Returns:
51
DatumInContext: New datum with extended context chain
52
"""
53
54
@property
55
def value(self):
56
"""
57
The actual data value.
58
59
Returns:
60
Any: The wrapped data value
61
"""
62
63
@property
64
def path(self):
65
"""
66
Path from immediate context to this datum.
67
68
Returns:
69
JSONPath: Path object (default: This() if no path specified)
70
"""
71
72
@property
73
def context(self):
74
"""
75
Parent context containing this datum.
76
77
Returns:
78
DatumInContext or None: Parent context or None for root
79
"""
80
81
@property
82
def full_path(self):
83
"""
84
Complete path from root to this datum.
85
86
Reconstructs the full path by traversing up the context chain
87
and composing all path segments.
88
89
Returns:
90
JSONPath: Complete path from root
91
"""
92
93
@property
94
def id_pseudopath(self):
95
"""
96
Path-like representation with ID fields substituted when available.
97
98
When auto_id_field is set, replaces path segments with ID values
99
from the data when present, creating more readable path representations.
100
101
Returns:
102
JSONPath: Path with ID substitutions
103
"""
104
```
105
106
### AutoIdForDatum Class
107
108
Special datum wrapper that uses the path as its value, supporting automatic ID field generation for data elements without explicit identifiers.
109
110
```python { .api }
111
class AutoIdForDatum(DatumInContext):
112
"""
113
Special DatumInContext where the value is the path leading up to it.
114
115
Used for automatic ID field generation when auto_id_field is enabled.
116
The value becomes the string representation of the datum's id_pseudopath.
117
"""
118
119
def __init__(self, datum, id_field=None):
120
"""
121
Initialize auto-ID datum.
122
123
Parameters:
124
- datum: DatumInContext, the underlying datum
125
- id_field: str, ID field name (default: uses global auto_id_field)
126
"""
127
128
@property
129
def value(self):
130
"""
131
String representation of the datum's id_pseudopath.
132
133
Returns:
134
str: Path-based identifier string
135
"""
136
137
@property
138
def path(self):
139
"""
140
The ID field name.
141
142
Returns:
143
str: ID field name used for this auto-ID datum
144
"""
145
146
@property
147
def context(self):
148
"""
149
The underlying datum.
150
151
Returns:
152
DatumInContext: Original datum this auto-ID is based on
153
"""
154
155
def in_context(self, context, path):
156
"""
157
Create new AutoIdForDatum with extended context.
158
159
Parameters:
160
- context: Parent context
161
- path: JSONPath from context
162
163
Returns:
164
AutoIdForDatum: New auto-ID datum with extended context
165
"""
166
```
167
168
## Usage Examples
169
170
### Basic Context Usage
171
172
```python
173
from jsonpath_rw.jsonpath import DatumInContext, Root, Fields
174
175
# Create datum with context
176
datum = DatumInContext(
177
value=42,
178
path=Fields('count'),
179
context=DatumInContext({'count': 42, 'name': 'test'})
180
)
181
182
print(datum.value) # 42
183
print(datum.full_path) # Fields('count')
184
```
185
186
### Automatic ID Field Generation
187
188
```python
189
import jsonpath_rw.jsonpath as jsonpath
190
from jsonpath_rw import parse
191
192
# Enable auto ID field
193
jsonpath.auto_id_field = 'id'
194
195
# Data with mixed ID presence
196
data = {
197
'users': [
198
{'id': 'user1', 'name': 'Alice'},
199
{'name': 'Bob'} # No explicit ID
200
]
201
}
202
203
# Query for auto-generated IDs
204
matches = parse('users[*].id').find(data)
205
values = [match.value for match in matches]
206
print(values) # ['users.user1', 'users.[1]']
207
```
208
209
### Context Chain Navigation
210
211
```python
212
from jsonpath_rw import parse
213
214
data = {
215
'company': {
216
'departments': [
217
{'name': 'Engineering', 'head': {'name': 'Alice'}}
218
]
219
}
220
}
221
222
matches = parse('company.departments[0].head.name').find(data)
223
match = matches[0]
224
225
print(match.value) # 'Alice'
226
print(match.path) # Fields('name')
227
print(match.context.value) # {'name': 'Alice'}
228
print(match.full_path) # company.departments.[0].head.name
229
```
230
231
### Building Context Manually
232
233
```python
234
from jsonpath_rw.jsonpath import DatumInContext, Fields, Index
235
236
# Build nested context manually
237
root_data = {'items': [{'name': 'test'}]}
238
root_datum = DatumInContext(root_data)
239
240
items_datum = DatumInContext(
241
value=[{'name': 'test'}],
242
path=Fields('items'),
243
context=root_datum
244
)
245
246
item_datum = DatumInContext(
247
value={'name': 'test'},
248
path=Index(0),
249
context=items_datum
250
)
251
252
name_datum = DatumInContext(
253
value='test',
254
path=Fields('name'),
255
context=item_datum
256
)
257
258
print(name_datum.full_path) # items.[0].name
259
```
260
261
### Extending Context Chains
262
263
```python
264
from jsonpath_rw.jsonpath import DatumInContext, Fields
265
266
# Create base datum
267
base = DatumInContext('value')
268
269
# Extend with context
270
extended = base.in_context(
271
context=DatumInContext({'nested': 'value'}),
272
path=Fields('nested')
273
)
274
275
print(extended.full_path) # nested
276
```
277
278
## Global Configuration
279
280
### Auto ID Field
281
282
```python { .api }
283
# Global variable controlling automatic ID field generation
284
auto_id_field = None # Default: disabled
285
```
286
287
When `auto_id_field` is set to a field name (typically `'id'`), the system automatically generates path-based identifiers for data elements. This is useful for tracking objects that don't have explicit ID fields.
288
289
**Example:**
290
291
```python
292
import jsonpath_rw.jsonpath as jsonpath
293
294
# Enable auto ID with 'id' field
295
jsonpath.auto_id_field = 'id'
296
297
# Now queries can access auto-generated IDs
298
# Objects with explicit 'id' fields use those values
299
# Objects without 'id' fields get path-based identifiers
300
```
301
302
## Error Handling
303
304
Context operations are generally safe, but some scenarios can cause issues:
305
306
- **Missing Parent Context**: Accessing `parent` operator when no parent exists will crash
307
- **Invalid Context Chains**: Malformed context chains may produce unexpected full_path results
308
- **Type Compatibility**: Some operations expect specific data types in the context chain