To effectively work with arrays in n8n, you’ll primarily use the Set node or expressions within other nodes. You can create a static array by setting a value in the Set node with an expression like [ 'item1', 'item2' ]
or build dynamic arrays of objects using data from previous nodes, such as {{ [{ "id": $json.userId, "status": "active" }] }}
. For manipulating existing arrays, the .append()
method is the recommended way to add new items safely within an expression.
Why Arrays Are the Backbone of Your Automations
Let’s be honest. When you first start with automation, you’re usually just passing single pieces of data from A to B. But the moment you need to handle a list of users, a batch of products, or multiple attachments, you’ve stepped into the world of arrays. So, what are they?
Think of an array as a shopping list. It’s a single container (list.json
) that holds multiple, related items (['milk', 'eggs', 'bread']
). In n8n, this structure is fundamental. You need it for:
- Looping: Processing each item in a list with nodes like Split in Batches.
- API Calls: Many APIs require you to send data, like a list of products to add to a cart, as an array of objects.
- Data Transformation: Aggregating results from multiple sources into a single, clean list before sending it to a database or spreadsheet.
Mastering how to create and manage these lists is the difference between a simple workflow and a powerful, scalable automation engine.
The Go-To Tool: Using the Set Node to Define Arrays
The Set node is your bread and butter for creating and modifying data in n8n, and it’s the perfect place to build an array from scratch. It’s explicit, easy to debug, and keeps your logic clean.
Creating a Simple Array (A List of Values)
Need a straightforward list? This is the easiest way. In a Set node, add a new value, give it a name (like mySimpleArray
), and switch to the expression editor.
To create an array of strings, you’d simply write:
{{ [ 'Task 1', 'Task 2', 'Task 3' ] }}
You can also pull in data from previous nodes:
{{ [ $json.userEmail, 'admin@example.com', 'support@example.com' ] }}
See? The square brackets []
are what tell n8n, “Hey, this is an array!”
Creating an Array of Objects (Complex Data)
Now, here’s where it gets really useful. Most of the time, especially with APIs, you won’t be sending a simple list. You’ll be sending an array of objects, where each object has its own properties.
Imagine you need to create a JSON body for an API that expects a list of products. In your Set node, the expression would look something like this:
{{ [{ "sku": "ABC-123", "quantity": 2 }, { "sku": "XYZ-789", "quantity": 5 }] }}
This creates an array containing two objects. The real power comes from making this dynamic. If you have the sku
and quantity
coming from a previous node, you can construct it like this:
{{ [{ "sku": $json.productSku, "quantity": $json.orderQuantity }] }}
This simple expression takes data from the incoming item and structures it perfectly for your next step.
Manipulating Arrays on the Fly with Expressions
Setting an array is one thing, but what about changing it? You don’t always need a full-blown Function node to add or merge data. You can do a lot right inside an expression.
Adding Items to an Existing Array: The .append()
Method
I’m going to save you some future headache. Your first instinct might be to use the standard JavaScript .push()
method to add an item to an array. Don’t. Due to the way n8n can sometimes re-evaluate expressions, using .push()
can lead to bizarre behavior, like your item being added multiple times. I’ve been there; it’s not fun to debug.
The correct, safe, and n8n-approved way is to use the .append()
method. It’s designed for this exact purpose.
{{ $json.myExistingArray.append('newItem') }}
This takes your original array, adds the new item, and returns a brand new, clean array. It’s predictable and reliable.
Merging Two Arrays Together
Have two separate lists you want to combine? The spread syntax (...
) is your best friend. It’s an elegant, modern way to merge arrays right in an expression.
{{ [...$json.arrayOne, ...$json.arrayTwo] }}
This one-liner takes all the items from arrayOne
, all the items from arrayTwo
, and combines them into a single, new array. It’s incredibly efficient.
Real-World Case Study: Building a Dynamic API Request
Let’s put this into practice. Imagine you’re pulling a list of new tasks from Notion and need to create them in Asana. Asana’s API might expect a payload like {"data": {"projects": ["12345"], "name": "My Task Name"}}
.
- Notion Node: Triggers when a new item is added to a database. It outputs the task name.
- Set Node (The ‘n8n set array’ step): Here, we set a property called
projectId
with an expression to create the array Asana needs:{{ ["12345"] }}
. We’re creating an array with a single, static project ID. - Asana Node: In the “Name” field, we map the task name from Notion:
{{ $json.taskName }}
. In the “Projects” field, we map the array we just created:{{ $json.projectId }}
.
By using the Set node to explicitly create the array, we ensure the data is perfectly formatted before it even reaches the Asana node. This makes the workflow easier to read and troubleshoot.
When to Use the Function Node
While expressions are powerful, they have their limits. If you need to perform complex logic—like filtering an array for specific values and then transforming (mapping) the remaining items—you’ll want to use the Function node. It gives you the full power of JavaScript to loop, filter, map, and reduce your data however you see fit. Think of it as your tool for heavy-duty array manipulation, while the Set node and expressions are for your everyday tasks.
Method | Best For | Example |
---|---|---|
Set Node | Creating new, well-structured arrays from scratch. | Setting a value to {{ [ $json.id1, $json.id2 ] }} |
Expressions | Simple manipulations like adding or merging. | {{ $json.myArray.append('new') }} |
Function Node | Complex logic like filtering, mapping, and reducing. | items.filter(i => i.json.active).map(i => i.json.name) |