or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

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

core-parsing.mddocs/

0

# Core Parsing and Expression Building

1

2

Parse JSONPath expressions from strings or build them programmatically using AST classes. JSONPath-NG provides a full parser for standard JSONPath syntax and supports programmatic construction for complex use cases.

3

4

## Capabilities

5

6

### String Parsing

7

8

Parse JSONPath expressions from strings into executable JSONPath objects.

9

10

```python { .api }

11

def parse(string: str) -> JSONPath:

12

"""

13

Parse a JSONPath string expression into a JSONPath object.

14

15

Args:

16

string: JSONPath expression string (e.g., '$.foo[*].bar')

17

18

Returns:

19

JSONPath object that can be used for find/update/filter operations

20

21

Raises:

22

JsonPathParserError: If the string contains invalid JSONPath syntax

23

"""

24

```

25

26

Usage example:

27

28

```python

29

from jsonpath_ng import parse

30

31

# Simple field access

32

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

33

34

# Complex nested paths

35

expr = parse('$.store.book[0].author')

36

37

# Wildcards and slicing

38

expr = parse('$.products[*].reviews[1:3]')

39

40

# Union expressions

41

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

42

```

43

44

### Root Expression

45

46

Reference to the root object in JSON data structure.

47

48

```python { .api }

49

class Root(JSONPath):

50

"""JSONPath referring to the root object. Concrete syntax is '$'."""

51

52

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

53

"""Find root object, returns single-element list containing root data"""

54

55

def update(self, data, val):

56

"""Replace entire root object with val"""

57

58

def filter(self, fn, data):

59

"""Apply filter function to root data"""

60

```

61

62

### This Expression

63

64

Reference to the current object in JSONPath context.

65

66

```python { .api }

67

class This(JSONPath):

68

"""JSONPath referring to current datum. Concrete syntax is '@' or '`this`'."""

69

70

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

71

"""Find current datum, returns single-element list"""

72

73

def update(self, data, val):

74

"""Replace current data with val"""

75

76

def filter(self, fn, data):

77

"""Apply filter function to current data"""

78

```

79

80

### Field Access

81

82

Access object fields by name, including wildcards and multi-field selection.

83

84

```python { .api }

85

class Fields(JSONPath):

86

"""JSONPath referring to object fields. Supports wildcards and multiple fields."""

87

88

def __init__(self, *fields: str):

89

"""

90

Initialize field accessor.

91

92

Args:

93

*fields: Field names to access. Use '*' for all fields.

94

"""

95

96

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

97

"""Find values for specified fields"""

98

99

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

100

"""Find values, creating empty objects for missing fields"""

101

102

def update(self, data, val):

103

"""Update specified fields with val"""

104

105

def update_or_create(self, data, val):

106

"""Update fields, creating them if they don't exist"""

107

108

def filter(self, fn, data):

109

"""Remove fields where filter function returns True"""

110

111

def reified_fields(self, datum) -> Tuple[str, ...]:

112

"""Get actual field names, expanding wildcards"""

113

114

@staticmethod

115

def get_field_datum(datum, field: str, create: bool) -> Optional[DatumInContext]:

116

"""Get datum for specific field, optionally creating if missing"""

117

```

118

119

### Array Indexing

120

121

Access array elements by numeric index.

122

123

```python { .api }

124

class Index(JSONPath):

125

"""JSONPath for array indices. Concrete syntax is '[n]'."""

126

127

def __init__(self, index: int):

128

"""

129

Initialize index accessor.

130

131

Args:

132

index: Array index (0-based, negative indices supported)

133

"""

134

135

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

136

"""Find element at specified index"""

137

138

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

139

"""Find element, padding array if index is beyond current length"""

140

141

def update(self, data, val):

142

"""Update element at specified index"""

143

144

def update_or_create(self, data, val):

145

"""Update element, expanding array if necessary"""

146

147

def filter(self, fn, data):

148

"""Remove element if filter function returns True"""

149

```

150

151

### Array Slicing

152

153

Access array slices using Python-style slice notation.

154

155

```python { .api }

156

class Slice(JSONPath):

157

"""JSONPath for array slices. Supports '[start:end:step]' and '[*]' syntax."""

158

159

def __init__(self, start: Optional[int] = None, end: Optional[int] = None, step: Optional[int] = None):

160

"""

161

Initialize slice accessor.

162

163

Args:

164

start: Start index (inclusive)

165

end: End index (exclusive)

166

step: Step size

167

"""

168

169

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

170

"""Find elements in slice range"""

171

172

def update(self, data, val):

173

"""Update all elements in slice range"""

174

175

def filter(self, fn, data):

176

"""Remove elements in slice where filter function returns True"""

177

```

178

179

### Expression Composition

180

181

Combine JSONPath expressions using composition operators.

182

183

```python { .api }

184

class Child(JSONPath):

185

"""JSONPath combining left and right expressions. Concrete syntax is 'left.right'."""

186

187

def __init__(self, left: JSONPath, right: JSONPath):

188

"""

189

Initialize child expression.

190

191

Args:

192

left: Parent JSONPath expression

193

right: Child JSONPath expression

194

"""

195

196

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

197

"""Find right expression results starting from left expression matches"""

198

199

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

200

"""Find with creation of missing intermediate objects"""

201

202

def update(self, data, val):

203

"""Update right expression targets within left expression matches"""

204

205

def update_or_create(self, data, val):

206

"""Update with creation of missing intermediate objects"""

207

208

def filter(self, fn, data):

209

"""Apply filter to right expression targets within left expression matches"""

210

211

class Union(JSONPath):

212

"""JSONPath union of results. Concrete syntax is 'left|right'."""

213

214

def __init__(self, left: JSONPath, right: JSONPath):

215

"""

216

Initialize union expression.

217

218

Args:

219

left: First JSONPath expression

220

right: Second JSONPath expression

221

"""

222

223

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

224

"""Find union of left and right expression results"""

225

226

def is_singular(self) -> bool:

227

"""Always returns False as unions produce multiple results"""

228

229

class Descendants(JSONPath):

230

"""JSONPath recursive descendant matching. Concrete syntax is 'left..right'."""

231

232

def __init__(self, left: JSONPath, right: JSONPath):

233

"""

234

Initialize descendants expression.

235

236

Args:

237

left: Ancestor JSONPath expression

238

right: Descendant JSONPath expression to match

239

"""

240

241

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

242

"""Find right expression matches recursively within left expression results"""

243

244

def update(self, data, val):

245

"""Update all descendant matches"""

246

247

def filter(self, fn, data):

248

"""Filter all descendant matches"""

249

250

def is_singular(self) -> bool:

251

"""Always returns False as descendants produce multiple results"""

252

```

253

254

### Conditional Expressions

255

256

Filter expressions based on conditions.

257

258

```python { .api }

259

class Where(JSONPath):

260

"""JSONPath filtering based on condition. Concrete syntax is 'left where right'."""

261

262

def __init__(self, left: JSONPath, right: JSONPath):

263

"""

264

Initialize where expression.

265

266

Args:

267

left: Base JSONPath expression

268

right: Condition JSONPath expression

269

"""

270

271

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

272

"""Find left expression results that have matches for right expression"""

273

274

def update(self, data, val):

275

"""Update matching left expression results"""

276

277

def filter(self, fn, data):

278

"""Apply filter to matching left expression results"""

279

280

class WhereNot(Where):

281

"""JSONPath filtering based on negated condition. Concrete syntax is 'left wherenot right'."""

282

283

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

284

"""Find left expression results that do NOT have matches for right expression"""

285

```

286

287

### Special Expressions

288

289

Additional expression types for advanced use cases.

290

291

```python { .api }

292

class Parent(JSONPath):

293

"""JSONPath matching parent node. Available via named operator '`parent`'."""

294

295

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

296

"""Find parent of current datum"""

297

298

class Intersect(JSONPath):

299

"""JSONPath intersection (not implemented). Concrete syntax is 'left&right'."""

300

301

def __init__(self, left: JSONPath, right: JSONPath):

302

"""Initialize intersection expression (not implemented)"""

303

304

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

305

"""Not implemented - raises NotImplementedError"""

306

307

def is_singular(self) -> bool:

308

"""Always returns False"""

309

```

310

311

## Programmatic Construction

312

313

Build JSONPath expressions programmatically without parsing strings:

314

315

```python

316

from jsonpath_ng.jsonpath import Root, Fields, Index, Child, Slice

317

318

# Equivalent to '$.foo[*].bar'

319

expr = Root().child(Fields('foo')).child(Slice()).child(Fields('bar'))

320

321

# Equivalent to '$.users[0].profile.name'

322

expr = Child(

323

Child(

324

Child(Root(), Fields('users')),

325

Index(0)

326

),

327

Child(Fields('profile'), Fields('name'))

328

)

329

330

# Using the convenience child() method

331

expr = Root().child(Fields('users')).child(Index(0)).child(Fields('profile')).child(Fields('name'))

332

```

333

334

## Parser and Lexer Configuration

335

336

```python { .api }

337

class JsonPathParser:

338

"""LALR parser for JSONPath expressions."""

339

340

def __init__(self, debug: bool = False, lexer_class=None):

341

"""

342

Initialize parser.

343

344

Args:

345

debug: Enable debug output

346

lexer_class: Custom lexer class (defaults to JsonPathLexer)

347

"""

348

349

def parse(self, string: str, lexer=None) -> JSONPath:

350

"""Parse JSONPath string into JSONPath object"""

351

352

def parse_token_stream(self, token_iterator) -> JSONPath:

353

"""Parse from token iterator"""

354

355

class JsonPathLexer:

356

"""Lexical analyzer for JSONPath expressions."""

357

358

def __init__(self, debug: bool = False):

359

"""

360

Initialize lexer.

361

362

Args:

363

debug: Enable debug output

364

"""

365

366

def tokenize(self, string: str) -> Iterator[Token]:

367

"""

368

Tokenize JSONPath string.

369

370

Args:

371

string: JSONPath expression string

372

373

Returns:

374

Iterator of tokens for parsing

375

"""

376

377

# Class attributes

378

literals: List[str] # List of literal characters

379

reserved_words: Dict[str, str] # Reserved word mappings

380

tokens: List[str] # List of token types

381

```

382

383

## Exceptions

384

385

```python { .api }

386

class JSONPathError(Exception):

387

"""Base exception for JSONPath operations"""

388

389

class JsonPathParserError(JSONPathError):

390

"""Parser-specific exceptions for invalid JSONPath syntax"""

391

392

class JsonPathLexerError(JSONPathError):

393

"""Lexer-specific exceptions for invalid tokens"""

394

```