JSON Matching Expressions library that allows declarative extraction of elements from JSON documents using a query language
npx @tessl/cli install tessl/pypi-jmespath@1.0.00
# JMESPath
1
2
JMESPath (pronounced "james path") allows you to declaratively specify how to extract elements from a JSON document using a query language designed specifically for JSON. It provides a simple yet powerful syntax for navigating complex JSON structures, supporting operations like accessing nested objects, filtering arrays, projecting data from collections, and applying built-in functions for data transformation.
3
4
## Package Information
5
6
- **Package Name**: jmespath
7
- **Language**: Python
8
- **Installation**: `pip install jmespath`
9
- **Version**: 1.0.1
10
- **License**: MIT
11
12
## Core Imports
13
14
```python
15
import jmespath
16
```
17
18
For accessing specific components:
19
20
```python
21
from jmespath import search, compile, Options
22
from jmespath.exceptions import (
23
JMESPathError, ParseError, JMESPathTypeError,
24
IncompleteExpressionError, LexerError, ArityError,
25
VariadictArityError, EmptyExpressionError, UnknownFunctionError
26
)
27
from jmespath import functions # For custom functions
28
```
29
30
## Basic Usage
31
32
```python
33
import jmespath
34
35
# Simple path extraction
36
data = {'foo': {'bar': 'baz'}}
37
result = jmespath.search('foo.bar', data)
38
# Returns: 'baz'
39
40
# Array operations
41
data = {'users': [{'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25}]}
42
names = jmespath.search('users[*].name', data)
43
# Returns: ['Alice', 'Bob']
44
45
# Filtering with conditions
46
adults = jmespath.search('users[?age >= `30`]', data)
47
# Returns: [{'name': 'Alice', 'age': 30}]
48
49
# Compiled expressions for reuse
50
expression = jmespath.compile('users[*].name')
51
names1 = expression.search(data1)
52
names2 = expression.search(data2)
53
```
54
55
## Architecture
56
57
JMESPath uses a multi-stage processing pipeline:
58
59
- **Lexer**: Tokenizes JMESPath expressions into a stream of tokens
60
- **Parser**: Builds an Abstract Syntax Tree (AST) from tokens using top-down operator precedence parsing
61
- **TreeInterpreter**: Evaluates the AST against JSON data using the visitor pattern
62
- **Functions**: Built-in function registry with type checking and argument validation
63
64
The architecture enables caching of parsed expressions for performance and provides comprehensive error reporting with precise location information.
65
66
## Capabilities
67
68
### Core Query Functions
69
70
Primary interface for searching JSON data with JMESPath expressions, supporting both one-time queries and compiled expressions for repeated use.
71
72
```python { .api }
73
def search(expression, data, options=None):
74
"""
75
Search data using JMESPath expression.
76
77
Args:
78
expression (str): JMESPath expression string
79
data: Python data structure to search (dict, list, etc.)
80
options (Options, optional): Options for controlling evaluation
81
82
Returns:
83
any: Extracted data matching the expression
84
"""
85
86
def compile(expression):
87
"""
88
Compile JMESPath expression into reusable parsed expression.
89
90
Args:
91
expression (str): JMESPath expression string
92
93
Returns:
94
ParsedResult: Object with search(data, options=None) method
95
"""
96
```
97
98
### Configuration Options
99
100
Control how JMESPath expressions are evaluated, including dictionary class selection and custom function registration.
101
102
```python { .api }
103
class Options:
104
"""Options to control how a JMESPath expression is evaluated."""
105
106
def __init__(self, dict_cls=None, custom_functions=None):
107
"""
108
Initialize evaluation options.
109
110
Args:
111
dict_cls: Class to use when creating dictionaries (default: dict)
112
custom_functions: Custom function registry instance
113
"""
114
```
115
116
### Exception Handling
117
118
Comprehensive error handling for different types of JMESPath failures, from syntax errors to type mismatches.
119
120
```python { .api }
121
class JMESPathError(ValueError):
122
"""Base exception for all JMESPath errors."""
123
124
class ParseError(JMESPathError):
125
"""Invalid JMESPath expression parse error."""
126
127
def __init__(self, lex_position, token_value, token_type, msg="Invalid jmespath expression"):
128
"""
129
Args:
130
lex_position (int): Position in expression where error occurred
131
token_value (str): Token value that caused error
132
token_type (str): Type of token that caused error
133
msg (str): Error message
134
"""
135
136
class IncompleteExpressionError(ParseError):
137
"""Incomplete JMESPath expression error."""
138
139
class LexerError(ParseError):
140
"""Lexical analysis error."""
141
142
class EmptyExpressionError(JMESPathError):
143
"""Empty JMESPath expression error."""
144
145
class ArityError(ParseError):
146
"""Wrong number of arguments to function."""
147
148
def __init__(self, expected, actual, name):
149
"""
150
Args:
151
expected (int): Expected number of arguments
152
actual (int): Actual number of arguments provided
153
name (str): Function name
154
"""
155
156
class VariadictArityError(ArityError):
157
"""Too few arguments for variadic function."""
158
159
class JMESPathTypeError(JMESPathError):
160
"""Type error in function argument."""
161
162
def __init__(self, function_name, current_value, actual_type, expected_types):
163
"""
164
Args:
165
function_name (str): Name of function
166
current_value: The problematic value
167
actual_type (str): Actual type found
168
expected_types (list): Expected types
169
"""
170
171
class UnknownFunctionError(JMESPathError):
172
"""Unknown function name error."""
173
```
174
175
## Built-in Functions
176
177
JMESPath provides a comprehensive set of built-in functions organized by functionality. All functions are used within JMESPath expressions, not called directly from Python.
178
179
### Mathematical Functions
180
181
```python { .api }
182
# Mathematical operations for numeric data
183
abs(number) # Absolute value
184
avg(array_number) # Average of numeric array
185
ceil(number) # Ceiling of number
186
floor(number) # Floor of number
187
max(array_number) # Maximum value in numeric array
188
min(array_number) # Minimum value in numeric array
189
sum(array_number) # Sum of numeric array
190
```
191
192
### Array Functions
193
194
```python { .api }
195
# Array manipulation and analysis
196
length(array|object|string) # Length of array, object, or string
197
reverse(array) # Reverse array order
198
sort(array) # Sort array
199
sort_by(array, expression) # Sort array by expression result
200
max_by(array, expression) # Find maximum element by expression
201
min_by(array, expression) # Find minimum element by expression
202
map(expression, array) # Apply expression to each array element
203
```
204
205
### Object Functions
206
207
```python { .api }
208
# Object manipulation operations
209
keys(object) # Get object keys as array
210
values(object) # Get object values as array
211
merge(object...) # Merge multiple objects (variadic)
212
```
213
214
### String Functions
215
216
```python { .api }
217
# String operations and testing
218
contains(array|string, any) # Check if array/string contains value
219
ends_with(string, string) # Check if string ends with suffix
220
starts_with(string, string) # Check if string starts with prefix
221
join(string, array_string) # Join string array with separator
222
```
223
224
### Type Functions
225
226
```python { .api }
227
# Type checking and conversion
228
type(any) # Get type of value ("string", "number", "array", "object", "boolean", "null")
229
not_null(any...) # Return first non-null value (variadic)
230
to_array(any) # Convert value to array
231
to_string(any) # Convert value to string
232
to_number(string) # Convert string to number
233
```
234
235
## Function Usage Examples
236
237
```python
238
# Mathematical functions
239
jmespath.search('avg(scores)', {'scores': [85, 92, 78, 96]})
240
# Returns: 87.75
241
242
# Array functions
243
jmespath.search('sort_by(users, &age)', {
244
'users': [{'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25}]
245
})
246
# Returns: [{'name': 'Bob', 'age': 25}, {'name': 'Alice', 'age': 30}]
247
248
# String functions
249
jmespath.search('join(`, `, names)', {'names': ['Alice', 'Bob', 'Charlie']})
250
# Returns: "Alice, Bob, Charlie"
251
252
# Type functions
253
jmespath.search('not_null(missing, backup, default)', {
254
'missing': None, 'backup': None, 'default': 'fallback'
255
})
256
# Returns: "fallback"
257
```
258
259
## Advanced Options Usage
260
261
```python
262
import jmespath
263
from collections import OrderedDict
264
265
# Using custom dictionary class for ordered output
266
options = jmespath.Options(dict_cls=OrderedDict)
267
result = jmespath.search('{name: name, age: age}', user_data, options)
268
269
# Compiled expressions with options
270
expression = jmespath.compile('{name: name, age: age}')
271
result = expression.search(user_data, options)
272
```
273
274
## Error Handling Patterns
275
276
```python
277
import jmespath
278
from jmespath.exceptions import ParseError, JMESPathTypeError
279
280
try:
281
result = jmespath.search('invalid..syntax', data)
282
except ParseError as e:
283
print(f"Syntax error at position {e.lex_position}: {e}")
284
except JMESPathTypeError as e:
285
print(f"Type error in {e.function_name}: {e}")
286
except jmespath.JMESPathError as e:
287
print(f"JMESPath error: {e}")
288
```
289
290
## Custom Functions
291
292
JMESPath supports custom functions through subclassing. Create custom functions by extending the base Functions class.
293
294
```python
295
import jmespath
296
from jmespath import functions
297
298
# Create a subclass of functions.Functions
299
class CustomFunctions(functions.Functions):
300
301
# Create methods starting with "_func_" and decorate with @signature
302
@functions.signature({'types': ['string']})
303
def _func_unique_letters(self, s):
304
# Given a string s, return sorted unique letters: 'ccbbadd' -> 'abcd'
305
return ''.join(sorted(set(s)))
306
307
@functions.signature({'types': ['number']}, {'types': ['number']})
308
def _func_my_add(self, x, y):
309
return x + y
310
311
# Use custom functions with Options
312
options = jmespath.Options(custom_functions=CustomFunctions())
313
314
# Apply custom functions in expressions
315
result = jmespath.search('my_add(`1`, `2`)', {}, options)
316
# Returns: 3
317
318
result = jmespath.search('foo.bar | unique_letters(@)',
319
{'foo': {'bar': 'ccbbadd'}}, options)
320
# Returns: "abcd"
321
```
322
323
### Custom Function Requirements
324
325
```python { .api }
326
@functions.signature(*signature_dicts)
327
def _func_function_name(self, *args):
328
"""
329
Custom function implementation.
330
331
Args:
332
signature_dicts: Type specifications for each parameter
333
Format: {'types': ['string', 'number', 'array', 'object', 'boolean', 'null']}
334
Special: {'types': [], 'variadic': True} for variadic functions
335
args: Function arguments matching signature types
336
337
Returns:
338
any: Function result
339
"""
340
```
341
342
## Types
343
344
```python { .api }
345
__version__: str # Library version string, currently "1.0.1"
346
347
class ParsedResult:
348
"""Compiled JMESPath expression returned by compile()."""
349
350
expression: str # Original expression string
351
parsed: dict # Parsed AST (internal use)
352
353
def search(self, data, options=None):
354
"""
355
Search data using the compiled expression.
356
357
Args:
358
data: Python data structure to search
359
options (Options, optional): Options for controlling evaluation
360
361
Returns:
362
any: Extracted data matching the expression
363
"""
364
```
365
366
## JMESPath Expression Language
367
368
JMESPath expressions use a JSON-specific query language with the following key syntax:
369
370
- **Basic access**: `foo.bar` - Access nested objects
371
- **Array indexing**: `foo[0]` - Access array elements by index
372
- **Array slicing**: `foo[1:3]` - Slice arrays
373
- **Wildcard**: `foo[*].bar` - Project over arrays
374
- **Multi-select**: `{name: name, id: id}` - Create new objects
375
- **Filtering**: `foo[?bar > 10]` - Filter arrays with conditions
376
- **Functions**: `length(foo)` - Apply built-in functions
377
- **Pipes**: `foo | bar` - Chain operations
378
- **Current node**: `@` - Reference current node in expressions
379
380
See [JMESPath Tutorial](http://jmespath.org/tutorial.html) for comprehensive language documentation.
381
382
## Command Line Interface
383
384
JMESPath includes a command-line tool for interactive JSON querying.
385
386
```bash
387
# Search JSON from stdin
388
echo '{"foo": {"bar": "baz"}}' | jp.py 'foo.bar'
389
390
# Search JSON from file
391
jp.py 'users[*].name' -f data.json
392
393
# Display AST for debugging
394
jp.py 'foo.bar' --ast
395
```
396
397
### Command Line Options
398
399
```python { .api }
400
# jp.py command line arguments:
401
# expression (required): JMESPath expression to evaluate
402
# -f, --filename: Input JSON file (default: stdin)
403
# --ast: Pretty print AST instead of searching
404
```