Overview
This tutorial explains how to retrieve, access, and process data in Torq workflows using advanced mechanisms.
Torq uses JSONPath to access data from event triggers and workflow steps. With advanced JSONPath syntax, you can extract specific values from complex structures (such as arrays of objects). For more advanced transformations, you can use Golang templates .
All data processing capabilities described here are also available as no-code steps.
Sample data
All examples in this guide use the following dataset:
{
"hosts": [
{
"name": "host1",
"interfaces": [
{
"name": "Interface 1 of Host 1",
"address": "10.10.10.1",
"weight": 10
},
{
"name": "Interface 2 of Host 1",
"address": "10.10.10.2",
"weight": 20
}
]
},
{
"name": "host2",
"interfaces": [
{
"name": "Interface 1 of Host 2",
"address": "20.20.20.1",
"weight": 10
},
{
"name": "Interface 2 of Host 2",
"address": "20.20.20.2",
"weight": 20
},
{
"name": "Interface 3 of Host 2",
"address": "20.20.20.3",
"weight": 30
}
]
}
]
}Arrays and collections
Workflow data often includes collections such as users, devices, or vulnerabilities. Torq supports multiple ways to access and manipulate these structures.
Note: Collections in Torq are zero-based (the first item has index 0).
Common template functions
len: returns the length (number of items) of the array provided as an argument.
For the collection above,{{ len $.hosts }}will return 2.index: returns a single item from a map or an array. The provided index can be either a numerical position in an array or a named key inside a map. The function can be used multiple times in a single template to access nested fields within a collection.
{{ (index (index $.hosts 0).interfaces 0).name }}returns the name of the first interface of the first host. For the collection above, the result will be Interface 1 of Host 1.[]: returns either a single item or a range of items.
{{ $.hosts[0] }}is equivalent to{{ index $.hosts 0 }}. It can be used for direct field access such as{{ $.hosts[0].name }}or nested access like{{ $.hosts[0].interfaces[0].name }}.
For the collection above,{{ $.hosts[0].interfaces[0].name }}will return Interface 1 of Host 1.
Access and slice data (JSONPath)
Torq supports the following JSONPath expressions for performing operations on arrays and collections. Indexes start at 0.
Expression | Description | Example |
| Returns the n-th element in the array |
|
| Returns a list consisting of items at indexes x and y |
|
| Returns a list consisting of the first x items of the array |
|
| Returns a list consisting of the last x items of the array |
|
| Returns a list of elements that match the specified expression |
|
| Returns a new list where each element is a field extracted from items in the original list |
|
Apply filters to arrays and collections
You can filter arrays and collections in JSONPath to return only the elements that match specific conditions, patterns, or combined logic expressions.
Filtering complete objects: the expression
$.hosts[1].interfaces[?(@.weight > 10)]will return a list of interfaces where the value of the weight key exceeds 10.Retrieving specific fields: the expression
$.hosts[1].interfaces[?(@.weight > 10)].namewill return a list of names rather than a list of complete interface objects. For the example above,$.hosts[1].interfaces[?(@.weight > 10)][0]will return Interface 2 of Host 2.Matching by JavaScript regular expression: the expression
$.hosts[1].interfaces[?(@.name=~ /(Interface [23])/)]will return a list of interfaces that contains interfaces 2 and 3.Matching by multiple expressions: can be performed by combining expressions using
&&(logical AND) and||(logical OR) operators. For example, the expression$.hosts[1].interfaces[?(@.weight > 20 && @.name=~ /(Interface [23])/)]will return a list containing only Interface 3 of Host 2.
Comparisons
Comparison operators are useful either when defining a conditional execution of a step or when a step argument value depends on a specific condition. Each of the below is a boolean comparison operator:
eq- Returns the boolean truth of arg1 == arg2ne- Returns the boolean truth of arg1 != arg2lt- Returns the boolean truth of arg1 < arg2gt- Returns the boolean truth of arg1 > arg2ge- Returns the boolean truth of arg1 >= arg2ieq- Returns the case-insensitive string comparison of arg1 and arg2 (==)ine- Returns the negation of a case-insensitive string comparison of arg1 and arg2 (!=)isNull- Returns true if the operand arg1 is Null (the actual word Null, not an empty argument)empty- Returns true when a JSON path is not defined or present in a step output
For example, if using these comparisons with the collection provided above:
{{ eq (len $.hosts) 2 }} and {{ ge (len $.hosts) 0 }} will return true, whereas {{ isNull $.hosts }} or {{ lt (len $.hosts[0].interfaces) 1 }} will return false.
Logical operators
Logical operators allow executing boolean logic using execution context fields or variables as arguments.
and: returns the boolean AND of its arguments by returning the first empty argument or the last argument; that is, "and x y" behaves as "if x then y else x". All the arguments are evaluated.
For example:{{ and (eq $.event.Scope_Action "Firing") (eq $.event.Scope_Env "Production") }}or: returns the boolean OR of its arguments by returning the first non-empty argument or the last argument; that is, "or x y" behaves as "if x then x else y". All the arguments are evaluated.
For example:{{ or (eq $.event.Scope_Action "Firing") (eq $.event.Scope_Action "Warning") }}not: returns the boolean negation of its single argument.
For example:{{ not (eq $.event.Scope_Action "Firing") }}
Short-circuit evaluation
Do not rely on short-circuit evaluation. If one of the conditions can be in a state that prevents its evaluation, advanced conditional structures should be used. For example, in the case of an array that can be empty, the following clause will not work: {{ and (gt (len $.array) 0) (eq $.array[1] 8) }}, because when the array is empty, the index evaluation will fail.
Useful template functions
Torq supports a broad set of Sprig functions (Golang templates), providing built-in tools for string manipulation, data formatting, logic, and date/time handling. Below are the most commonly used template functions; for the full list, see the Sprig Functions: Add Dynamic Data Logic to Your Workflows article.
Function | Description | Example > Output |
default | If the evaluated value is empty, the given default will be returned |
|
jsonEscape | Escapes a string so it can be safely embedded in JSON (adds backslashes for quotes, newlines, etc.) |
|
b64enc, b64dec | Encodes or decodes the provided data using Base64 encoding |
|
upper, lower | Converts a string to uppercase or lowercase |
|
len | Returns the length of a string, array, map, or object |
|
Advanced templates
Torq supports advanced templates that generate dynamic output (text, markdown, or scripts) populated with data from the workflow context.
The syntax from the Golang Template package allows iterating over collections of data and objects using the range function.
For example, you can build a template that displays the number of hosts and lists their names.
Examples
Basic range usage
Template
We currently have {{ len $.hosts }} hosts and their names are:
{{ range $index, $host := $.hosts }} {{ $host.name }} {{ end }}Output
We currently have 2 hosts and their names are: host1 host2
The range function performs the following actions:
Iterates over each item in
$.hosts(no output is generated if the array is empty)Defines two temporary variables available inside the loop:
$index> index of the current item (zero-based)$host> the current object
Outputs the
namefield for each host
If / else
Another example is using conditional logic in a template:
{{ if (gt (len $.hosts) 1) -}} Multiple hosts found {{- else -}} Single host found {{- end }}If more than one host exists, the output will be:
Multiple hosts foundIf only one host exists, the output will be:
Single host found
Render lists with range
The range function can also generate dynamic lists, for example in an Interact Markdown widget:
{{ range $item := $.interact.answers.use_cases }}
- {{ $item }}
{{ end }}This iterates over the array and renders each item as a separate bullet point.
Improve template verbosity with $index
You can enhance templates by including the $index variable to produce more detailed and readable output.
Template with improved verbosity
We currently have {{ len $.hosts }} hosts and their names are:
{{ range $index, $host := $.hosts }} The name of host {{ $index }} is {{ $host.name }} {{ end }}Output
We currently have 2 hosts and their names are: The name of host 0 is host1 The name of host 1 is host2
As seen in the example, the index is zero-based.
Nested range constructs
The range construct can be nested to iterate over arrays within arrays, such as interfaces inside hosts.
Template using nested range constructs
We currently have {{ len $.hosts }} hosts and their names are:
{{ range $index, $host := $.hosts }}
----------------------------------------------
The name of host {{ $index }} is {{ $host.name }}
It has {{ len $host.interfaces }} interfaces:
{{ range $interfaceidx, $interface := $host.interfaces }}
Interface number {{ $interfaceidx }} is named "{{$interface.name}}" and has an IP address of {{$interface.address}}
{{ end }}
----------------------------------------------
{{ end }}Output
We currently have 2 hosts and their names are:
----------------------------------------------
The name of host 0 is host1
It has 2 interfaces:
Interface number 0 is named "Interface 1 of Host 1" and has an IP address of 10.10.10.1
Interface number 1 is named "Interface 2 of Host 1" and has an IP address of 10.10.10.2
----------------------------------------------
----------------------------------------------
The name of host 1 is host2
It has 3 interfaces:
Interface number 0 is named "Interface 1 of Host 2" and has an IP address of 20.20.20.1
Interface number 1 is named "Interface 2 of Host 2" and has an IP address of 20.20.20.2
Interface number 2 is named "Interface 3 of Host 2" and has an IP address of 20.20.20.3
----------------------------------------------
Combine range variables with other data
Template variables such as $index can be combined with other workflow data to reference related items in different arrays.
{{ index $.some_other_step.list_of_responses $idx }}In this example:
indexretrieves an element from the array$.some_other_step.list_of_responses$idxrepresents the current index from arangeloop (0, 1, 2, ...)
Troubleshooting
Escaping URLs
Use the urlquery function to safely escape URLs directly inside templates, without requiring a separate step.


