Advanced mapping using JMESPath syntax
JMESPath helps you pick and transform values inside JSON. (It’s a query language, meaning it lets you “ask” JSON for exactly the value you want.) In Torii, you can use it to extract values from nested objects, work with lists, and format the final value that gets mapped into a field.
To learn the syntax and try examples, use the official JMESPath playground: https://jmespath.org/
One simple way to use it: write your JMESPath query on the top, paste your JSON below it, and see the result instantly.
The following guide walks you step by step from the basics to advanced concepts.
1) Basics: paths and indexing
Simple JMESPath expressions look like dot notation paths, for example: app.name.
Example: Get a field
Input
{
"app": {
"id": 1,
"name": "Torii"
}
}JMESPath query
app.nameResult
"Torii" // Note how a string always starts and ends with the " character
Example: Get a value by list index
Input
{ "apps": [ { "name": "Torii" }, { "name": "AWS" } ] }JMESPath query
apps[0].nameResult
"Torii" // This is also a string which starts and ends with the " character
2) Lists: [] means “do this for every item”
apps[].name means “for every item in the apps list (array), return its name”.
Example: Get all names
Input
{
"apps": [
{ "id": 1, "name": "Torii" },
{ "id": 2, "name": "AWS" }
]
}JMESPath query
apps[].nameResult
["Torii", "AWS"] // Note how an array always starts and ends with [] characters
3) Turn a list into text: join
join glues list items together using a separator (like a comma) into a string.
Example: Join app names with a comma
Input
{ "apps": [ { "name": "Torii" }, { "name": "AWS" } ] }JMESPath query
join(',', apps[].name)Result
"Torii,AWS"
// Note how the result is a string ("") and not an array ([])4) Pipes and the current value: | and @
-
|means: take the result and pass it to the next function. -
@means: “the current value” (think: “whatever we have so far”).
Example: Join app names using | and @
Input
{ "apps": [ { "name": "Torii" }, { "name": "AWS" } ] }JMESPath query
apps[].name | join(',', @)Result
"Torii,AWS"
This works in two steps:
-
apps[].nameproduces the array["Torii", "AWS"] -
join(',', @)joins the current value into a string
5) Functions that run “per item”: map and &
Sometimes you need to apply the same function to every item in a list.
-
map(expression, list)returns a new list after applyingexpressionto each item. -
&is used to write an expression that will be applied to each item. Inside that expression, you usually use@to refer to the current item.
Example: Convert every id to text
Input
{ "apps": [ { "id": 1 }, { "id": 2 } ] }JMESPath query
map(&to_string(@), apps[].id)Result
["1", "2"]
When to use map(...) vs []
- Use
[]when you’re picking fields from each item, likeapps[].idorapps[].name. - Use
map(...)when you need to run a function per item, especially when you need&and@, like converting each item:map(&to_string(@), apps[].id).
A quick way to remember it:
-
[]selects values -
map(...)transforms each value
6) Converting formats: to_string and to_number
Some functions only work if the value is in the right format, like text vs number.
-
join(...)expects a list of strings - math functions like
sum(...)expect numbers
Example: Get all ids as one comma-separated string
Input
{ "apps": [ { "id": 1 }, { "id": 2 } ] }JMESPath query
apps[].id | map(&to_string(@), @) | join(',', @)Result
"1,2"
Example: Convert strings that look like numbers into numbers
Input
{ "costs": ["10", "20", "3"] }JMESPath query
map(&to_number(@), costs)Result
[10, 20, 3]
7) Filtering: keep only the items you want
Filtering means: keep only the items that match a condition.
Example: Keep only the AWS app
Input
{
"apps": [
{
"id": 1,
"name": "Torii"
},
{
"id": 2,
"name": "AWS"
}
]
}JMESPath query
apps[?name == 'AWS']Result
[
{
"id": 2,
"name": "AWS"
}
]8) Bigger example: filter, pick nested values, and format output
Example: Filter list and join user names
This will:
- keep only the AWS app
- take its
userslist and turn it into one combined list ([]) - join the list into one string using
" and "
Input
{
"apps": [
{
"name": "Torii",
"users": ["Joe", "Daniel"]
},
{
"name": "AWS",
"users": ["Bob", "Claire"]
}
]
}JMESPath query
apps[?name == 'AWS'].users[] | join(' and ', @)Result
"Bob and Claire"
// apps[?name == 'AWS'] --> { "name": "AWS", "users": ["Bob", "Claire"] }
// .users[] --> ["Bob", "Claire"]
// join(' and ', @) --> "Bob and Claire"9) Add up values: sum
sum(arrayOfNumbers) adds up numbers in an array.
Example: Sum values that come back as strings
Input
{ "lineItems": [ {"price": "19.99"}, {"price": "10"} ] }JMESPath query
sum(map(&to_number(@), lineItems[].price))Result
29.99 // lineItems[].price --> ["19.99", "10"] // map(&to_number(@), ...) --> [19.99, 10] // sum(...) --> 29.99
Common use cases in Torii mappings
- Extract a single value:
a.b.c - Get a list of values:
apps[].name - Build text from a list:
apps[].name | join(', ', @) - Filter items by a field:
apps[?name == 'AWS'] - Work with a nested list:
apps[].users[] - Convert formats when needed:
to_string(...),to_number(...) - Calculate totals:
sum(...)
Using LLM and AI agents to help with JMESPath
ChatGPT, Gemini, Microsoft Co-pilot, Claude and other LLM chatbots are great at formulating JMESPath queries based on your goal. For example, you can use the following prompt:
For the following input JSON:
{
"apps": [
{
"name": "Torii",
"users": ["Joe", "Daniel"]
},
{
"name": "AWS",
"users": ["Bob", "Claire"]
}
]
}
Please provide a JMESPath query that will result in the users
of AWS combined to a string, separated by a comma.
Please explain how it works as well.A response from the LLM may look like:
JMESPath query:
join(', ', apps[?name=='AWS'] | [0].users)
How it works:
apps[?name=='AWS'] filters the apps array down to only the objects whose name is "AWS". Result is an array (typically with one item).
| [0] pipes that filtered array into an index operation, taking the first matching object (the AWS app object).
.users selects its users array, e.g. ["Bob","Claire"].
join(', ', ...) joins that array into a single string with , between entries, producing: "Bob, Claire".How to test your JMESPath queries
- Copy a real JSON example from the Torii step you’re mapping
- Paste it into the JMESPath playground (https://jmespath.org/)
- Write your query and verify the output
- Make sure the final output matches what the target field expects
- If you are going to send the result over email or Slack/Teams message, it should be a string or a number.
- If you are going to send this value in a subsequent API call, it might need to be an array or object.
- In general, these rules apply:
- If the target field is text, end with a string (often
join(...)). - If it’s a number field, return a number (use
to_number(...), and useto_number(...)beforesum(...)). - If the field expects a list, return an array like
["a", "b"].
- If the target field is text, end with a string (often