Standard JMESPath Only
This guide demonstrates jpx using only standard JMESPath functions - no extensions. This is useful when:
- You need queries portable to other JMESPath implementations
- You’re learning JMESPath fundamentals
- You want to understand what’s possible without extensions
You can also use jpx --strict to enforce standard-only mode, which will error if you accidentally use an extension function.
Standard Functions Reference
JMESPath defines 26 built-in functions:
| Function | Description |
|---|---|
abs(n) | Absolute value |
avg(arr) | Average of numbers |
ceil(n) | Round up |
contains(subject, search) | Check if contains value |
ends_with(str, suffix) | Check string suffix |
floor(n) | Round down |
join(sep, arr) | Join array to string |
keys(obj) | Get object keys |
length(val) | Length of array/string/object |
map(&expr, arr) | Apply expression to each element |
max(arr) | Maximum value |
max_by(arr, &expr) | Element with max expression value |
merge(obj1, obj2, ...) | Merge objects |
min(arr) | Minimum value |
min_by(arr, &expr) | Element with min expression value |
not_null(val1, val2, ...) | First non-null value |
reverse(arr) | Reverse array or string |
sort(arr) | Sort array |
sort_by(arr, &expr) | Sort by expression |
starts_with(str, prefix) | Check string prefix |
sum(arr) | Sum of numbers |
to_array(val) | Convert to array |
to_number(val) | Convert to number |
to_string(val) | Convert to string |
type(val) | Get value type |
values(obj) | Get object values |
Sample Data
We’ll use this sample dataset throughout the guide:
cat > books.json << 'EOF'
{
"library": {
"name": "City Library",
"books": [
{"id": 1, "title": "The Great Gatsby", "author": "F. Scott Fitzgerald", "year": 1925, "genres": ["fiction", "classic"], "rating": 4.2, "available": true},
{"id": 2, "title": "To Kill a Mockingbird", "author": "Harper Lee", "year": 1960, "genres": ["fiction", "classic"], "rating": 4.5, "available": false},
{"id": 3, "title": "1984", "author": "George Orwell", "year": 1949, "genres": ["fiction", "dystopian"], "rating": 4.3, "available": true},
{"id": 4, "title": "Pride and Prejudice", "author": "Jane Austen", "year": 1813, "genres": ["fiction", "romance"], "rating": 4.4, "available": true},
{"id": 5, "title": "The Catcher in the Rye", "author": "J.D. Salinger", "year": 1951, "genres": ["fiction", "classic"], "rating": 3.9, "available": false},
{"id": 6, "title": "Brave New World", "author": "Aldous Huxley", "year": 1932, "genres": ["fiction", "dystopian"], "rating": 4.1, "available": true},
{"id": 7, "title": "The Hobbit", "author": "J.R.R. Tolkien", "year": 1937, "genres": ["fiction", "fantasy"], "rating": 4.6, "available": true},
{"id": 8, "title": "Animal Farm", "author": "George Orwell", "year": 1945, "genres": ["fiction", "satire"], "rating": 4.0, "available": false}
]
}
}
EOF
Basic Selection
Access Nested Data
jpx --strict 'library.name' books.json
Output: "City Library"
Get All Books
jpx --strict 'library.books' books.json
Select Specific Fields
jpx --strict 'library.books[*].title' books.json
Output:
["The Great Gatsby", "To Kill a Mockingbird", "1984", "Pride and Prejudice", "The Catcher in the Rye", "Brave New World", "The Hobbit", "Animal Farm"]
Project Multiple Fields
jpx --strict 'library.books[*].{title: title, author: author}' books.json
Output:
[
{"title": "The Great Gatsby", "author": "F. Scott Fitzgerald"},
{"title": "To Kill a Mockingbird", "author": "Harper Lee"},
...
]
Filtering
Filter by Condition
jpx --strict 'library.books[?available == `true`].title' books.json
Output:
["The Great Gatsby", "1984", "Pride and Prejudice", "Brave New World", "The Hobbit"]
Filter by Numeric Comparison
jpx --strict 'library.books[?rating >= `4.3`].{title: title, rating: rating}' books.json
Output:
[
{"title": "To Kill a Mockingbird", "rating": 4.5},
{"title": "1984", "rating": 4.3},
{"title": "Pride and Prejudice", "rating": 4.4},
{"title": "The Hobbit", "rating": 4.6}
]
Filter by Year Range
jpx --strict 'library.books[?year >= `1940` && year < `1960`].title' books.json
Output:
["1984", "The Catcher in the Rye", "Animal Farm"]
Filter with String Functions
# Books by authors starting with "J"
jpx --strict 'library.books[?starts_with(author, `J`)].{title: title, author: author}' books.json
Output:
[
{"title": "Pride and Prejudice", "author": "Jane Austen"},
{"title": "The Catcher in the Rye", "author": "J.D. Salinger"},
{"title": "The Hobbit", "author": "J.R.R. Tolkien"}
]
Filter with Contains
# Books with "The" in the title
jpx --strict 'library.books[?contains(title, `The`)].title' books.json
Output:
["The Great Gatsby", "The Catcher in the Rye", "The Hobbit"]
Check Array Membership
# Books in the "dystopian" genre
jpx --strict 'library.books[?contains(genres, `dystopian`)].title' books.json
Output:
["1984", "Brave New World"]
Sorting
Sort by Field
jpx --strict 'sort_by(library.books, &year)[*].{title: title, year: year}' books.json
Output (oldest first):
[
{"title": "Pride and Prejudice", "year": 1813},
{"title": "The Great Gatsby", "year": 1925},
{"title": "Brave New World", "year": 1932},
...
]
Sort Descending (Reverse)
jpx --strict 'reverse(sort_by(library.books, &rating))[*].{title: title, rating: rating}' books.json
Output (highest rated first):
[
{"title": "The Hobbit", "rating": 4.6},
{"title": "To Kill a Mockingbird", "rating": 4.5},
{"title": "Pride and Prejudice", "rating": 4.4},
...
]
Sort Simple Arrays
jpx --strict 'sort(library.books[*].year)' books.json
Output:
[1813, 1925, 1932, 1937, 1945, 1949, 1951, 1960]
Aggregation
Count Items
jpx --strict 'length(library.books)' books.json
Output: 8
Count Filtered Items
jpx --strict 'length(library.books[?available == `true`])' books.json
Output: 5
Sum Values
jpx --strict 'sum(library.books[*].year)' books.json
Output: 15512
Average
jpx --strict 'avg(library.books[*].rating)' books.json
Output: 4.25
Min and Max
jpx --strict '{
oldest_year: min(library.books[*].year),
newest_year: max(library.books[*].year),
lowest_rating: min(library.books[*].rating),
highest_rating: max(library.books[*].rating)
}' books.json
Output:
{
"oldest_year": 1813,
"newest_year": 1960,
"lowest_rating": 3.9,
"highest_rating": 4.6
}
Find Element with Min/Max
# Highest rated book
jpx --strict 'max_by(library.books, &rating).{title: title, rating: rating}' books.json
Output:
{"title": "The Hobbit", "rating": 4.6}
# Oldest book
jpx --strict 'min_by(library.books, &year).{title: title, year: year}' books.json
Output:
{"title": "Pride and Prejudice", "year": 1813}
Object Operations
Get Keys
jpx --strict 'keys(library.books[0])' books.json
Output:
["id", "title", "author", "year", "genres", "rating", "available"]
Get Values
jpx --strict 'values(library.books[0])' books.json
Output:
[1, "The Great Gatsby", "F. Scott Fitzgerald", 1925, ["fiction", "classic"], 4.2, true]
Merge Objects
jpx --strict 'merge(library.books[0], {checked_out: `true`, due_date: `2025-02-01`})' books.json
Output:
{
"id": 1,
"title": "The Great Gatsby",
"author": "F. Scott Fitzgerald",
"year": 1925,
"genres": ["fiction", "classic"],
"rating": 4.2,
"available": true,
"checked_out": true,
"due_date": "2025-02-01"
}
Type Conversions
Check Type
jpx --strict 'type(library.books)' books.json
Output: "array"
jpx --strict 'type(library.books[0].rating)' books.json
Output: "number"
Convert to String
jpx --strict 'library.books[*].{title: title, year_str: to_string(year)}' books.json
Convert to Number
echo '{"value": "42"}' | jpx --strict 'to_number(value)'
Output: 42
Convert to Array
jpx --strict 'to_array(library.name)' books.json
Output: ["City Library"]
String Operations
Join Array Elements
jpx --strict 'join(`, `, library.books[*].title)' books.json
Output: "The Great Gatsby, To Kill a Mockingbird, 1984, Pride and Prejudice, The Catcher in the Rye, Brave New World, The Hobbit, Animal Farm"
Check Prefix/Suffix
# Titles ending with specific words
jpx --strict 'library.books[?ends_with(title, `Rye`)].title' books.json
Output: ["The Catcher in the Rye"]
The Map Function
The map function applies an expression to each element:
# Extract just the year from each book
jpx --strict 'map(&year, library.books)' books.json
Output:
[1925, 1960, 1949, 1813, 1951, 1932, 1937, 1945]
# Create formatted strings
jpx --strict 'map(&{book: title, published: year}, library.books)' books.json
Handling Nulls
First Non-Null Value
echo '{"a": null, "b": null, "c": "found"}' | jpx --strict 'not_null(a, b, c)'
Output: "found"
Null-Safe Field Access
echo '{"items": [{"name": "a", "value": 1}, {"name": "b"}]}' | \
jpx --strict 'items[*].{name: name, value: not_null(value, `0`)}'
Output:
[
{"name": "a", "value": 1},
{"name": "b", "value": 0}
]
Pipelines
Chain operations with the pipe operator |:
# Filter, sort, and take top 3
jpx --strict 'library.books
| [?available == `true`]
| sort_by(@, &rating)
| reverse(@)
| [:3]
| [*].{title: title, rating: rating}' books.json
Output:
[
{"title": "The Hobbit", "rating": 4.6},
{"title": "Pride and Prejudice", "rating": 4.4},
{"title": "1984", "rating": 4.3}
]
Complex Example: Library Report
Combining multiple standard functions:
jpx --strict '{
library_name: library.name,
total_books: length(library.books),
available_count: length(library.books[?available == `true`]),
checked_out_count: length(library.books[?available == `false`]),
average_rating: avg(library.books[*].rating),
rating_range: {
min: min(library.books[*].rating),
max: max(library.books[*].rating)
},
year_range: {
oldest: min(library.books[*].year),
newest: max(library.books[*].year)
},
top_rated: max_by(library.books, &rating).title,
authors: sort(library.books[*].author),
available_titles: sort(library.books[?available == `true`][*].title)
}' books.json
Output:
{
"library_name": "City Library",
"total_books": 8,
"available_count": 5,
"checked_out_count": 3,
"average_rating": 4.25,
"rating_range": {"min": 3.9, "max": 4.6},
"year_range": {"oldest": 1813, "newest": 1960},
"top_rated": "The Hobbit",
"authors": ["Aldous Huxley", "F. Scott Fitzgerald", "George Orwell", "George Orwell", "Harper Lee", "J.D. Salinger", "J.R.R. Tolkien", "Jane Austen"],
"available_titles": ["1984", "Brave New World", "Pride and Prejudice", "The Great Gatsby", "The Hobbit"]
}
When to Use Extensions
Standard JMESPath is powerful for basic transformations, but you’ll want extensions for:
- String manipulation:
split,trim,lower,upper,replace - Date/time:
from_epoch,format_date,date_diff - Advanced math:
median,stddev,round,percentile - Grouping:
group_by,frequencies,unique - Text processing:
tokens,stems,word_count - Hashing:
sha256,md5,base64_encode - And 350+ more functions
To see what’s available:
jpx --list-functions
jpx --search "group"
jpx --describe group_by