JSON data workflow helpers
Last Update: Jan 2025 • Est. Read Time: 5 MINJSON data helpers allow you to manipulate, format, and extract information from the JSON data generated or received within workflows.
In this article:
- Each
- With
- Lookup
- To JSON
- Parse JSON
- Parse Int / Parse Float
- Parse Bool
- Transform
- Map
- Included Resource Attribute
Each
The {{#each}}
block helper iterates through an array or object and concatenates each found value into a string.
- Given steps.1.attributes.data.letters = ["a", "b", "c"] OR {"firstLetter": "a", "secondLetter": "b", "thirdLetter": "c"}
{{#each steps.1.attributes.data.letters}}test{{/each}}
resolves to the string"testtesttest"
The value at each index or key can be accessed using the this
instance variable.
- Given steps.1.attributes.data.letters = ["a", "b", "c"] OR {"firstLetter": "a", "secondLetter": "b", "thirdLetter": "c"}
{{#each steps.1.attributes.data.letters}}{{this}}, {{/each}}
resolves to the string"a, b, c, "
Data path notation can access nested attribute values when working with sequentially nested objects.
- Given steps.1.attributes.data.letters = [{"letter": "a"}, {"letter": "b"}, {"letter": "c"}] OR {"firstLetter": {"letter": "a"}, "secondLetter": {"letter": "b"}, "thirdLetter": {"letter": "c"}}
{{#each steps.1.attributes.data.letters}}{{this.letter}}, {{/each}}
resolves to the string"a, b, c, "
The trailing comma and whitespace in the above examples may be undesirable in certain scenarios. Fortunately, @first
and @last
helper variables can be used in conjunction with conditional helpers such as {{#if}}
to define behavior on the first or last iteration respectively, allowing a character like a comma to be omitted from the final loop. Learn more
- Given steps.1.attributes.data.letters = ["a", "b", "c"] OR {"firstLetter": "a", "secondLetter": "b", "thirdLetter": "c"}
{{#each steps.1.attributes.data}}{{this}}{{#if @last}}{{else}}, {{/if}}{{/each}}
resolves to the string"a, b, c"
Additional @index
and @key
helper variables are also available to represent the current loop iteration number and object attribute name, respectively.
- Given steps.1.attributes.data = {"firstLetter": "a", "secondLetter": "b", "thirdLetter": "c"}
{{#each steps.1.attributes.data}}{{@index}}-{{@key}}: {{this}}{{#if @last}}{{else}}, {{/if}}{{/each}}
resolves to the string"0-firstLetter: a, 1-secondLetter: b, 2-thirdLetter: c"
Note: Nested {{#each}}
blocks can access iteration variables via depth-based paths. For example, @../index
can be used to access and reference the parent index.
As a block helper, {{#each}}
has access to the {{else}}
sub-helper, allowing multiple statements to be chained together, should the initially targeted array or object be empty or not exist.
{{#each steps.1.attributes.data.array1}}{{this}}{{else each steps.1.attributes.data.array2}}{{this}}{{else}}No items found{{/each}}
To parse and fully convert stringified JSON into literal JSON, use the /#fn:parseJSON
function helper. This will require an additional workflow step, such as "Transform Generic."
With
The {{#with}}
block helper accepts an object or an array as an argument, and allows contained values to be locally referenced by key or index.
- Given steps.1.attributes.data.hero = {firstName": "Peter", "lastName": "Parker"}
{{#with steps.1.attributes.data.hero}}My name is {{firstName}} {{lastName}}{{/with}}
resolves to the string"My name is Peter Parker"
- Given steps.1.attributes.data.hero = ["Peter", "Parker"]
{{#with steps.1.attributes.data.hero}}My name is {{0}} {{1}}{{/with}}
resolves to the string"My name is Peter Parker"
As a block helper, {{#with}}
has access to the {{else}}
block, allowing multiple statements to be chained together, should the initial statement resolves to a null
value.
{{#with steps.1.attributes.data.hero1}}{{firstName}} {{lastName}}{{else with steps.1.attributes.data.hero2}}{{firstName}} {{lastName}}{{else}}No heroes found{{/with}}
Lookup
The {{lookup}}
helper retrieves the value of an attribute using its key name, making it useful for dynamically referencing object data. It accepts two parameters: an object, and a key that specifies the desired data within the object.
- Given steps.1.attributes.data = {firstName": "Peter", "lastName": "Parker"}
{{lookup steps.1.attributes.data 'firstName'}}
resolves to the string"Peter"
Like all helper expressions, the lookup
helper only outputs a string. If the value of the identified attribute is an array, its items will be concatenated into a single string, without array brackets. If the value is an object, it will be represented as the string "[object Object]".
To interpret arrays and objects as stringified JSON data, use the toJSON
helper.
To JSON
The {{toJSON}}
helper converts an object into a stringified JSON format, including escaped characters. This is useful when array data is missing standard brackets or when object data defaults to the string "[object Object]".
- Given steps.1.attributes.data = {"hero": {firstName": "Peter", "lastName": "Parker"}, "team": ["Spiderman", "Daredevil"], {"identifier": "hero"}
{{toJSON steps.1.attributes.data.team}}
resolves to the stringified JSON"[\"Spiderman\",\"Daredevil\"]"
{{toJSON (lookup steps.1.attributes.data steps.1.attributes.data.identifier)}}
resolves to the stringified JSON"{\"firstName\":\"Peter\",\"lastName\":\"Parker\"}"
To parse and reference a specific value within stringified JSON, see the parseJSON
helper.
To parse and fully convert stringified JSON into literal JSON, see /#fn:parseJSON
. Making this conversion sequentially will require an additional workflow step, such as "Transform Generic."
Parse JSON
The /#fn:parseJSON
function helper accepts stringified representations of JSON data and converts to an output of literal JSON data.
- Given steps.1.attributes.data.stringifiedJSON = "{\"firstName\":\"Peter\",\"lastName\":\"Parker\"}"
/#fn:parseJSON,steps.1.attributes.data.stringifiedJSON
resolves to the object{"firstName": "Peter", "lastName": "Parker"}
To capture an output of stringified JSON data, see the {{toJSON}}
helper.
The {{#parseJSON}}
block helper similarly accepts stringified JSON data. However, this helper's functionality is more aligned with the {{#with}}
helper, as it will only extract specific values by key or index.
- Given steps.1.attributes.data.stringifiedHero = "{\"firstName\":\"Peter\",\"lastName\":\"Parker\"}"
{{#parseJSON steps.1.attributes.data.stringifiedHero}}My name is {{firstName}} {{lastName}}{{/parseJSON}}
resolves to the string"My name is Peter Parker"
- Given steps.1.attributes.data.stringifiedHero = "[\"Peter\",\"Parker\"]"
{{#parseJSON steps.1.attributes.data.stringifiedHero}}My name is {{0}} {{1}}{{/parseJSON}}
resolves to the string"My name is Peter Parker"
Parse Int / Parse Float
The /#fn:parseInt
function helper converts a stringified number value into a standard number-type integer value, while /#fn:parseFloat
converts a stringified number value into a number-type value with any included decimals (also known as a "float").
Any string that begins with a non-numeric character will result in a number value of 0
. Any stringified number with additional non-numeric characters will result in the number up to the first non-numeric character
- Given steps.1.attributes.data.number = "10"
/#fn:parseInt,steps.1.attributes.data.number
resolves to the number value10
- Given steps.1.attributes.data.number = "10.90"
/#fn:parseFloat,steps.1.attributes.data.number
resolves to the number value10.9
/#fn:parseInt,steps.1.attributes.data.number
resolves to the number value10
- Given steps.1.attributes.data.number = "10abc"
/#fn:parseFloat,steps.1.attributes.data.number
resolves to the number value10
- Given steps.1.attributes.data.number = "abc10"
/#fn:parseInt,steps.1.attributes.data.number
resolves to the number value0
Parse Bool
The /#fn:parseBool
helper converts a stringified boolean value (true
or false
) into a standard boolean value. Any unrecognized input will default to false
.
- Given steps.1.attributes.data.open = "true"
/#fn:parseBool,steps.1.attributes.data.open
resolves to the boolean valuetrue
Transform
The /#fn:transform
helper performs bulk updates to the names of object keys in an array of objects and returns the full array with the updated keys.
- Given steps.1.message = [{"subject": "message a", "preview": "hello"}, {"subject": "message b", "preview": "goodbye"}]
/#fn:transform,steps.1.messages,title=subject,body=preview
resolves to the array
[{"title": "message a", "body": "hello"}, {"title": "message b", "body": "goodbye"}]
Map
Given an array of sequential objects, the /#fn:map
function helper assembles the values of a specified recurring object key and outputs them into a unique array. For example, an agent can use this helper to take an array of customer objects and create a new array containing just the listed email addresses.
- Given steps.1.attributes.data = {"customers": [{"name": "Agent A", "email": "email-a@example.com"}, {"name": "Agent B", "email": "email-b@example.com"}]}
/#fn:map,steps.1.attributes.data.customers,email
resolves to the array["email-a@example.com", "email-b@example.com"]
In addition to arrays, this helper can be used on sequential objects with a repeated key attribute.
- Given steps.1.attributes.data = {"firstAgent": {"name": "Agent A", "email": "email-a@example.com"}, "secondAgent": {"name": "Agent B", "email": "email-b@example.com"}}
/#fn:map,steps.1.attributes.data,email
resolves to the array
["email-a@example.com", "email-b@example.com"]
For sequential array values, the desired index can target the desired values from the array.
- Given steps.1.attributes.data = {"firstAgent": ["Agent A", "email-a@example.com"], "secondAgent": ["Agent B", "email-b@example.com"]}
/#fn:map,steps.1.attributes.data,1
resolves to the array["email-a@example.com", "email-b@example.com"]
If a specific target is not defined, the entire array will be returned in full. Additionally, strings can be mapped to return an array of individual characters.
- Given steps.1.name = "Bruce"
/#fn:map,steps.1.name
resolves to the array["B", "r", "u", "c", "e"]
Included Resource Attribute
The /#fn:findIncludedResourceAttribute
function helper takes an array of objects as an argument, and targets one if the objects from which to return a specified attribute value. The targeted object is identified as the first object that contains a match for a set of provided attribute values.
For example, in an array of message objects, this helper could return the channel used for a message containing a specified subject line, or it could return the subject line for a message by a specified direction and channel.
- Given steps.1.messages = [{"subject": "message a", "direction": "in", "channel": "email"}, {"subject": "message b", "direction": "out", "channel": "email"}, {"subject": "message c", "direction": "in", "channel": "sms"}]
/#fn:findIncludedResourceAttribute,steps.1.messages,subject=message a,channel
resolves to the string"email"
/#fn:findIncludedResourceAttribute,steps.1.messages,direction=in,channel=sms,subject
resolves to the string"message c"
When matching a value to target an object, only string-type values can used for matching, although selecting nested child attributes via data path is supported. The output will always be the data type of the queried attribute.
- Given steps.1.attributes.data = [{"operations": {"start": "combine", "end": "reduce"}, "numbers": [1, 3, 5]}]
/#fn:findIncludedResourceAttribute,steps.1.attributes.data,operations.start=combine,numbers
resolves to the array[1, 3, 5]