jsontoolskit.org
JSON and JSON Schema utilities, in the browser
Say hi →

JMESPath Tester

AWS CLI --query · Ansible json_query · projections, filters, functions

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.

Paste JSON.

How to test a JMESPath expression

  1. Paste the JSON — usually whatever aws … --output json just printed.
  2. Write the expression, or click one of the field chips under the box to start from a real path in your document.
  3. The result updates on every keystroke, with a one-line description of its shape underneath: whether you got an array, an object or null.
  4. 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:

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.