or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

command-line.mdcore-parsing.mdextensions.mdindex.mdpath-operations.md

path-operations.mddocs/

0

# Path Operations

1

2

Core operations for finding, updating, and filtering data using JSONPath expressions. These operations preserve context information and provide full path tracking for located data elements.

3

4

## Capabilities

5

6

### Data Context Management

7

8

JSONPath-NG preserves complete path information and context for all located data elements.

9

10

```python { .api }

11

class DatumInContext:

12

"""Represents a datum along a path from a context."""

13

14

def __init__(self, value, path: JSONPath = None, context: 'DatumInContext' = None):

15

"""

16

Initialize datum with context.

17

18

Args:

19

value: The actual data value

20

path: JSONPath to this datum

21

context: Parent datum context

22

"""

23

24

@classmethod

25

def wrap(cls, data) -> 'DatumInContext':

26

"""Wrap raw data in DatumInContext if not already wrapped"""

27

28

def in_context(self, context, path) -> 'DatumInContext':

29

"""Place this datum within another context"""

30

31

@property

32

def full_path(self) -> JSONPath:

33

"""Complete path from root to this datum"""

34

35

@property

36

def id_pseudopath(self) -> JSONPath:

37

"""Path with IDs substituted when available"""

38

39

value: Any # The actual data value

40

path: JSONPath # JSONPath to this location

41

context: Optional['DatumInContext'] # Parent context

42

```

43

44

Usage example:

45

46

```python

47

from jsonpath_ng import parse

48

49

data = {'users': [{'name': 'Alice', 'id': 1}, {'name': 'Bob', 'id': 2}]}

50

expr = parse('$.users[*].name')

51

52

matches = expr.find(data)

53

for match in matches:

54

print(f"Value: {match.value}")

55

print(f"Full path: {match.full_path}")

56

print(f"Context: {match.context.value}")

57

```

58

59

### Finding Data

60

61

Locate data elements matching JSONPath expressions.

62

63

```python { .api }

64

class JSONPath:

65

def find(self, data) -> Iterable[DatumInContext]:

66

"""

67

Find all data elements matching this JSONPath expression.

68

69

Args:

70

data: JSON data structure to search

71

72

Returns:

73

Iterable of DatumInContext objects containing matching values and their paths

74

"""

75

76

def find_or_create(self, data) -> Iterable[DatumInContext]:

77

"""

78

Find matching elements, creating missing intermediate objects.

79

80

Args:

81

data: JSON data structure to search/modify

82

83

Returns:

84

Iterable of DatumInContext objects, creating empty objects for missing paths

85

"""

86

```

87

88

Usage examples:

89

90

```python

91

from jsonpath_ng import parse

92

93

data = {

94

'store': {

95

'book': [

96

{'title': 'Book 1', 'price': 10.99},

97

{'title': 'Book 2', 'price': 15.99}

98

]

99

}

100

}

101

102

# Find all book titles

103

title_expr = parse('$.store.book[*].title')

104

matches = title_expr.find(data)

105

titles = [match.value for match in matches] # ['Book 1', 'Book 2']

106

107

# Find with creation of missing paths

108

missing_expr = parse('$.store.magazine[*].title')

109

matches = missing_expr.find_or_create(data) # Creates empty magazine array

110

```

111

112

### Updating Data

113

114

Modify data elements at JSONPath locations.

115

116

```python { .api }

117

class JSONPath:

118

def update(self, data, val):

119

"""

120

Update all matching locations with val. Only updates existing paths.

121

122

Args:

123

data: JSON data structure to modify

124

val: New value to set, or callable(old_value, parent_dict, key) -> new_value

125

126

Returns:

127

Modified data structure (same object, modified in place)

128

"""

129

130

def update_or_create(self, data, val):

131

"""

132

Update matching locations with val, creating missing paths.

133

134

Args:

135

data: JSON data structure to modify

136

val: New value to set, or callable(old_value, parent_dict, key) -> new_value

137

138

Returns:

139

Modified data structure (same object, modified in place)

140

"""

141

```

142

143

Usage examples:

144

145

```python

146

from jsonpath_ng import parse

147

148

data = {'users': [{'name': 'Alice', 'age': 25}, {'name': 'Bob', 'age': 30}]}

149

150

# Update all ages to 35

151

age_expr = parse('$.users[*].age')

152

updated_data = age_expr.update(data, 35)

153

154

# Update with function

155

def increment_age(old_val, parent, key):

156

return old_val + 1

157

158

updated_data = age_expr.update(data, increment_age)

159

160

# Update single user by index

161

single_expr = parse('$.users[0].name')

162

updated_data = single_expr.update(data, 'Alice Smith')

163

164

# Create missing path

165

missing_expr = parse('$.users[*].status')

166

updated_data = missing_expr.update_or_create(data, 'active')

167

```

168

169

### Filtering Data

170

171

Remove data elements based on filter conditions.

172

173

```python { .api }

174

class JSONPath:

175

def filter(self, fn, data):

176

"""

177

Filter matching elements using predicate function.

178

179

Args:

180

fn: Predicate function that returns True for elements to remove

181

data: JSON data structure to filter

182

183

Returns:

184

Filtered data structure with matching elements removed

185

"""

186

```

187

188

Usage examples:

189

190

```python

191

from jsonpath_ng import parse

192

193

data = {

194

'products': [

195

{'name': 'Widget A', 'price': 10.00, 'stock': 5},

196

{'name': 'Widget B', 'price': 15.00, 'stock': 0},

197

{'name': 'Widget C', 'price': 20.00, 'stock': 10}

198

]

199

}

200

201

# Remove out-of-stock products

202

expr = parse('$.products[*]')

203

filtered_data = expr.filter(lambda item: item['stock'] == 0, data)

204

205

# Remove expensive products

206

price_expr = parse('$.products[*].price')

207

filtered_data = price_expr.filter(lambda price: price > 15.00, data)

208

209

# Remove specific fields

210

name_expr = parse('$.products[*].name')

211

filtered_data = name_expr.filter(lambda x: True, data) # Removes all name fields

212

```

213

214

### Automatic ID Generation

215

216

Configure automatic ID field generation for consistent object identification.

217

218

```python { .api }

219

# Module-level configuration

220

import jsonpath_ng.jsonpath as jsonpath

221

222

jsonpath.auto_id_field: Optional[str] = None # Field name for auto-generated IDs

223

224

class AutoIdForDatum(DatumInContext):

225

"""

226

Special DatumInContext that generates automatic IDs based on path.

227

Used when auto_id_field is configured globally.

228

229

The value is always the path leading up to it (not including the ID field),

230

with any ID fields along the way replacing path segments.

231

"""

232

233

def __init__(self, datum, id_field: Optional[str] = None):

234

"""

235

Initialize auto-ID datum.

236

237

Args:

238

datum: Source DatumInContext

239

id_field: Field name for ID (defaults to global auto_id_field)

240

"""

241

242

@property

243

def value(self) -> str:

244

"""Auto-generated ID based on id_pseudopath of the datum"""

245

246

@property

247

def path(self) -> str:

248

"""ID field name"""

249

250

@property

251

def context(self) -> DatumInContext:

252

"""Original datum context"""

253

254

def in_context(self, context, path) -> 'AutoIdForDatum':

255

"""Place this auto-ID datum within another context"""

256

257

def __eq__(self, other) -> bool:

258

"""Compare with another AutoIdForDatum"""

259

```

260

261

Usage example:

262

263

```python

264

import jsonpath_ng.jsonpath as jsonpath

265

from jsonpath_ng import parse

266

267

# Enable auto-ID generation

268

jsonpath.auto_id_field = 'id'

269

270

data = {'users': [{'name': 'Alice'}, {'name': 'Bob'}]}

271

272

# Find auto-generated IDs

273

id_expr = parse('$.users[*].id')

274

matches = id_expr.find(data)

275

ids = [match.value for match in matches] # ['users.0', 'users.1']

276

277

# Mix with existing IDs

278

data = {'users': [{'name': 'Alice', 'id': 'alice'}, {'name': 'Bob'}]}

279

matches = id_expr.find(data)

280

ids = [match.value for match in matches] # ['alice', 'users.1']

281

```

282

283

### Path Utilities

284

285

Helper functions for path manipulation and data structure management.

286

287

```python { .api }

288

def _create_list_key(dict_: dict) -> list:

289

"""

290

Internal helper: Add list to dictionary and return it.

291

Used for list creation in update_or_create operations.

292

293

Args:

294

dict_: Dictionary to add list to

295

296

Returns:

297

Empty list that was added to dictionary

298

"""

299

300

def _clean_list_keys(struct_):

301

"""

302

Internal helper: Replace special list keys with actual lists.

303

Used to clean up data structures after update_or_create operations.

304

305

Args:

306

struct_: Data structure to clean

307

308

Returns:

309

Cleaned data structure with LIST_KEY placeholders replaced by lists

310

"""

311

```

312

313

### Advanced Path Navigation

314

315

Navigate between related data elements using context information.

316

317

```python { .api }

318

class Parent(JSONPath):

319

"""JSONPath that matches the parent node of the current match."""

320

321

def find(self, datum) -> List[DatumInContext]:

322

"""

323

Find parent context of current datum.

324

325

Args:

326

datum: Current DatumInContext

327

328

Returns:

329

List containing parent DatumInContext

330

331

Raises:

332

Error if no parent context exists

333

"""

334

```

335

336

Usage example:

337

338

```python

339

from jsonpath_ng import parse

340

341

data = {

342

'company': {

343

'departments': [

344

{'name': 'Engineering', 'employees': [{'name': 'Alice'}, {'name': 'Bob'}]},

345

{'name': 'Sales', 'employees': [{'name': 'Carol'}]}

346

]

347

}

348

}

349

350

# Find employee names and their department

351

expr = parse('$.company.departments[*].employees[*].name.`parent`.`parent`.name')

352

matches = expr.find(data)

353

dept_names = [match.value for match in matches] # ['Engineering', 'Engineering', 'Sales']

354

```

355

356

## Global Configuration

357

358

```python { .api }

359

# Module-level constants and configuration

360

NOT_SET: object # Sentinel value for missing data

361

LIST_KEY: object # Special key used internally for list operations

362

363

# Configuration variables

364

auto_id_field: Optional[str] = None # Enable automatic ID generation

365

```

366

367

## Error Handling

368

369

Common error patterns and exception handling:

370

371

```python

372

from jsonpath_ng import parse

373

from jsonpath_ng.exceptions import JsonPathParserError

374

375

try:

376

# Invalid JSONPath syntax

377

expr = parse('$.invalid[syntax')

378

except JsonPathParserError as e:

379

print(f"Parse error: {e}")

380

381

# Handle missing data gracefully

382

data = {'users': [{'name': 'Alice'}]}

383

expr = parse('$.users[*].age') # Age field doesn't exist

384

385

matches = expr.find(data) # Returns empty list, no exception

386

values = [match.value for match in matches] # []

387

388

# Safe updates

389

updated = expr.update(data, 25) # No-op, returns original data unchanged

390

```