JMESPath Tester
JMESPath is not a dialect of JSONPath, it is a different language — and it is the one the AWS CLI, Ansible and the Azure CLI actually speak. Paste the JSON your command returned, write the expression you were going to put after --query, and see what it evaluates to before you go back to the terminal.
How to test a JMESPath expression
- Paste the JSON — usually whatever
aws … --output jsonjust printed. - Write the expression, or click one of the field chips under the box to start from a real path in your document.
- The result updates on every keystroke, with a one-line description of its shape underneath: whether you got an array, an object or
null. - Copy the expression into your command. Remember to quote it in the shell —
--query "Reservations[*].Instances[].InstanceId".
JMESPath is not JSONPath
They look similar for the first ten characters and then diverge completely, which is why an expression copied from a JSONPath answer fails in the AWS CLI with a parse error that names a token rather than the problem. The differences that actually catch people:
- No leading
$. The root is implicit.$.usersis a syntax error;usersis the expression. - No recursive descent. There is no
... If you do not know where a field lives, you have to say the path — which is what the chips under the input box are for. - Filters use backticks for literals.
users[?age > `30`]. Without the backticks30is read as a field name, the comparison is against nothing, and you get an empty list rather than an error. - Projections stop at a scalar.
users[*].namereturns a list. Chaining another[*]after a scalar does not error — it returnsnull, silently. []flattens,[*]does not.users[].tags[]gives one flat list of tags;users[*].tagsgives a list of lists.
The parts worth knowing
Multiselect — reshaping the output
This is the feature that has no JSONPath equivalent and the reason most people end up here.
users[*].{who: name, years: age} builds new objects with the keys you name, so a
wide API response becomes exactly the two columns you wanted. The list form,
users[*].[name, age], gives arrays instead — which is what you feed to
--output text for a tab-separated table.
Pipes
A pipe stops a projection and starts a new expression on the result:
users[*].age | sort(@) | reverse(@). Without the pipes, sort would be
applied inside the projection to each individual age, which is not an error and not what you meant.
@ means "the current result".
Built-in functions
length, keys, values, sort,
sort_by, min_by, max_by, join,
to_string, to_number, contains,
starts_with, ends_with, not_null, map.
sort_by and friends take an expression reference with &:
sort_by(users, &age).
Why an empty result is not an error
JMESPath returns null for anything it cannot find, and an empty list for a projection
that matched nothing. It does not raise. That is the right behaviour for a query language embedded
in a CLI, and it is also why a typo in a field name looks exactly like "there is no such data".
This page says which of the two you are looking at — the status line distinguishes a
null result from an empty array, and the chips tell you the field names the document
really has.
FAQ
Which implementation does this use?
jmespath 0.16, the reference JavaScript implementation, loaded on demand and cached. It is the same compliance suite the Python jmespath library used by the AWS CLI is tested against, so an expression that works here works there.
Why does my filter return everything?
Almost always an unquoted literal. [?type == 'ec2'] compares against a raw string literal in single quotes; [?count > `5`] compares against a JSON literal in backticks. Double quotes mean an identifier, not a string — [?type == "ec2"] compares the field type with the field ec2.
How do I get a flat table out?
Multiselect list form plus --output text: users[*].[name, age, email]. Each inner array becomes one tab-separated line. For a header row you want the hash form and --output table instead.
Is my JSON uploaded?
No. The expression is evaluated in your browser. The only network request the page makes is fetching the JMESPath library itself, once.
What if I actually wanted JSONPath?
Use the JSONPath tester — that is the $.. language, supported by jsonpath-plus, Jayway and most Java tooling. For jq syntax, the jq playground.