/n8n-tutorials

How to use expressions in n8n?

Learn how to use expressions in n8n to dynamically access, manipulate, and transform data in workflows with step-by-step examples and best practices.

Matt Graham, CEO of Rapid Developers

Book a call with an Expert

Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.

Book a free consultation

How to use expressions in n8n?

Expressions in n8n are a powerful way to dynamically access, manipulate, and transform data within your workflows. They allow you to reference data from previous nodes, perform calculations, manipulate strings, and create conditional logic. You can use expressions in most fields across n8n nodes by wrapping your code in double curly braces like {{ $your_expression }}.

 

Understanding n8n Expressions

 

Expressions in n8n provide a way to work with data dynamically in your workflows. They enable you to:

  • Access data from previous nodes
  • Transform data on the fly
  • Perform calculations
  • Implement conditional logic
  • Manipulate strings and other data types

 

Step 1: Accessing the Expression Editor

 

To use expressions in n8n, you need to know how to access the expression editor:

  1. In your workflow, click on a node that you want to configure.
  2. Find the field where you want to use an expression.
  3. Look for the Expression Editor button (looks like { }) on the right side of the field.
  4. Click this button to open the Expression Editor.

Alternatively, you can type {{ directly in the field to start an expression.

 

Step 2: Understanding the Basics of Expressions

 

All expressions in n8n are wrapped in double curly braces: {{ }}

Inside these braces, you can write JavaScript code, use n8n variables, or utilize built-in methods.

For example:

{{ 2 + 2 }}

This simple expression will output 4.

 

Step 3: Accessing Data from Previous Nodes

 

One of the most common uses of expressions is to access data from previous nodes:

  1. To access data from the first output item of the previous node:

    {{ $node["Previous Node Name"].json.fieldName }}
  2. To access data from a specific item in a previous node's output:

    {{ $node["Previous Node Name"].json["fieldName"] }}
  3. To access data from a specific index in an array:

    {{ $node["Previous Node Name"].json.arrayField[0] }}

 

Step 4: Using the Current Node Data

 

You can also reference data within the current execution:

  1. To access the current item being processed:

    {{ $json.fieldName }}
  2. To access all items in the current execution:

    {{ $items }}
  3. To access a specific index from all items:

    {{ $items[0].json.fieldName }}

 

Step 5: Working with Variables and Parameters

 

n8n provides several special variables you can use in expressions:

  1. Workflow variables:

    {{ $workflow.id }}
    {{ $workflow.name }}
    {{ $workflow.active }}
  2. Execution variables:

    {{ $execution.id }}
    {{ $execution.mode }}
    {{ $execution.resumeUrl }}
  3. Environment variables:

    {{ $env.MY\_VARIABLE }}

 

Step 6: String Manipulation

 

You can perform various string operations in expressions:

  1. Concatenation:

    {{ "Hello, " + $json.name + "!" }}
  2. Template literals (for more readable code):

    {{ `Hello, ${$json.name}!` }}
  3. String methods:

    {{ $json.email.toLowerCase() }}
    {{ $json.name.toUpperCase() }}
    {{ $json.text.trim() }}
    {{ $json.message.slice(0, 10) }}

 

Step 7: Working with Numbers and Math

 

Perform mathematical operations within expressions:

  1. Basic arithmetic:

    {{ $json.price \* $json.quantity }}
    {{ $json.total / $json.count }}
    {{ $json.value + 10 }}
    {{ $json.number - 5 }}
  2. Using Math functions:

    {{ Math.round($json.price) }}
    {{ Math.floor($json.value) }}
    {{ Math.ceil($json.number) }}
    {{ Math.max($json.a, $json.b, $json.c) }}
  3. Formatting numbers:

    {{ $json.price.toFixed(2) }}

 

Step 8: Date and Time Operations

 

Work with dates in your expressions:

  1. Getting the current date and time:

    {{ new Date().toISOString() }}
    {{ Date.now() }}
  2. Formatting dates:

    {{ new Date($json.timestamp).toLocaleDateString() }}
    {{ new Date($json.created\_at).toLocaleTimeString() }}
  3. Date calculations:

    // Add 7 days to a date
    {{ new Date(new Date($json.date).getTime() + (7 _ 24 _ 60 _ 60 _ 1000)).toISOString() }}

 

Step 9: Conditional Logic

 

Implement decision-making in your expressions:

  1. Ternary operator for simple conditions:

    {{ $json.age >= 18 ? "Adult" : "Minor" }}
  2. More complex conditions:

    {{ 
      $json.status === "active" ? 
     "Account is active" : 
     ($json.status === "pending" ? 
       "Account is pending approval" : 
       "Account is inactive")
    }}
  3. Logical operators:

    {{ $json.isSubscribed && $json.hasConfirmedEmail ? "Fully registered" : "Incomplete registration" }}

 

Step 10: Array Operations

 

Manipulate arrays in your expressions:

  1. Map through an array:

    {{ 
      $json.items.map(item => {
     return {
       id: item.id,
       name: item.name.toUpperCase()
     };
      })
    }}
  2. Filter an array:

    {{ 
      $json.products.filter(product => product.price > 100)
    }}
  3. Find in an array:

    {{ 
      $json.users.find(user => user.id === $json.searchId)
    }}
  4. Reduce an array:

    {{ 
      $json.orderItems.reduce((total, item) => total + (item.price \* item.quantity), 0)
    }}

 

Step 11: Object Manipulation

 

Work with objects in your expressions:

  1. Creating new objects:

    {{ 
      {
     fullName: $json.firstName + " " + $json.lastName,
     email: $json.email.toLowerCase(),
     isActive: $json.status === "active"
      }
    }}
  2. Merging objects:

    {{ 
      {...$json, updated: true, timestamp: Date.now()}
    }}
  3. Extracting specific properties:

    {{ 
      (({name, email, id}) => ({name, email, id}))($json)
    }}

 

Step 12: Using Regular Expressions

 

Leverage regular expressions for pattern matching:

  1. Testing if a string matches a pattern:

    {{ /^[A-Za-z0-9.\_%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,}$/.test($json.email) }}
  2. Extracting parts of a string:

    {{ 
      $json.url.match(/https://([^/]+)/)[1]
    }}
  3. Replacing text:

    {{ 
      $json.text.replace(/sensitive/gi, "[REDACTED]")
    }}

 

Step 13: Using JSON Methods

 

Work with JSON data in your expressions:

  1. Parse JSON from a string:

    {{ 
      JSON.parse($json.jsonString)
    }}
  2. Convert to JSON string:

    {{ 
      JSON.stringify($json.data)
    }}
  3. Pretty print JSON:

    {{ 
      JSON.stringify($json, null, 2)
    }}

 

Step 14: Error Handling in Expressions

 

Handle potential errors in your expressions:

  1. Using the nullish coalescing operator:

    {{ 
      $json.user?.name ?? "Unknown User"
    }}
  2. Using try-catch:

    {{ 
      (function() {
     try {
       return JSON.parse($json.possiblyInvalidJson);
     } catch (error) {
       return { error: "Invalid JSON" };
     }
      })()
    }}
  3. Checking if properties exist:

    {{ 
      $json.hasOwnProperty('email') ? $json.email : 'No email provided'
    }}

 

Step 15: Working with n8n Built-in Methods

 

n8n provides several built-in utility methods:

  1. $itemIndex - the index of the current item:

    {{ 
      "Processing item #" + $itemIndex
    }}
  2. $if - for conditional logic:

    {{ 
      $if($json.status === "active",
       "User is active",
       "User is not active")
    }}
  3. $jmespath - for querying JSON:

    {{ 
      $jmespath($json, "users[?age > `30`].name")
    }}

 

Step 16: Complex Expression Examples

 

Here are some more advanced examples of what you can do with expressions:

  1. Generate a UUID:

    {{ 
      'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
     var r = Math.random() \* 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
     return v.toString(16);
      })
    }}
  2. Format a phone number:

    {{ 
      $json.phoneNumber.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3')
    }}
  3. Calculate time difference in hours:

    {{ 
      Math.round((new Date() - new Date($json.timestamp)) / (1000 _ 60 _ 60))
    }}

 

Step 17: Using Expressions with HTTP Requests

 

When working with HTTP Request nodes, expressions are particularly useful:

  1. Dynamic URL construction:

    {{ 
      `https://api.example.com/users/${$json.userId}/profile`
    }}
  2. Building query parameters:

    {{ 
      `https://api.example.com/search?q=${encodeURIComponent($json.searchTerm)}&limit=${$json.limit}`
    }}
  3. Constructing headers:

    {{ 
      {
     "Authorization": `Bearer ${$node["Auth Node"].json.accessToken}`,
     "Content-Type": "application/json",
     "X-Custom-Header": $json.customValue
      }
    }}

 

Step 18: Using Expressions with If Node

 

The If Node relies heavily on expressions for its conditions:

  1. Simple comparison:

    {{ 
      $json.status === "approved"
    }}
  2. Multiple conditions:

    {{ 
      $json.age >= 18 && $json.hasConsent === true
    }}
  3. Complex logic:

    {{ 
      ($json.userType === "premium" || $json.subscriptionMonths > 6) && $json.accountActive === true
    }}

 

Step 19: Using Expressions with Function Nodes

 

In Function nodes, you don't need to use the double curly braces syntax, but you can reference the same variables and data:

// Example Function Node code
const items = [];

// Process each input item
for (let i = 0; i < $input.all().length; i++) {
  const item = $input.all()[i];
  
  // Transform the data
  const newItem = {
    id: item.json.id,
    name: item.json.name.toUpperCase(),
    email: item.json.email.toLowerCase(),
    processedAt: new Date().toISOString()
  };
  
  items.push({json: newItem});
}

return items;

 

Step 20: Debugging Expressions

 

When your expressions don't work as expected, try these debugging techniques:

  1. Use the Set node to output expression results:
  • Create a Set node with a field called "debug"
  • Set its value to the expression you want to test
  • Execute the workflow and check the output
  1. Break down complex expressions:
  • Split complex expressions into smaller parts
  • Test each part separately
  • Combine them once each part works correctly
  1. Use console.log in Function nodes:
    // In a Function node
    console.log('Data to debug:', $input.item);
    return $input.item;

 

Step 21: Best Practices for Using Expressions

 

Follow these guidelines to use expressions effectively:

  • Keep expressions readable by breaking complex logic into smaller parts
  • Use template literals (`${variable}`) instead of concatenation when possible
  • Consider using Function nodes for very complex logic instead of cramming it all into expressions
  • Be careful with optional chaining (?.) when properties might be undefined
  • Use descriptive node names to make $node references clearer
  • Comment your complex expressions using the Expression Editor's comment feature
  • Test expressions with sample data before deploying workflows

 

Step 22: Common Expression Pitfalls and Solutions

 

Avoid these common mistakes:

  1. Missing quotes around property names with special characters:
  • Wrong: {{ $json.user-name }}
  • Correct: {{ $json["user-name"] }}
  1. Not handling null or undefined values:
  • Problem: {{ $json.user.email }} (crashes if user is null)
  • Solution: {{ $json.user?.email ?? "No email" }}
  1. Case sensitivity issues:
  • Remember that property names are case-sensitive
  • $json.Name is different from $json.name
  1. Forgetting to parse numeric strings:
  • Problem: {{ $json.price + $json.tax }} (concatenates if they're strings)
  • Solution: {{ Number($json.price) + Number($json.tax) }}

 

Step 23: Using Expressions with Loops

 

When working with arrays and loops:

  1. Map transformation:

    {{ 
      $json.items.map(item => {
     return {
       id: item.id,
       formattedPrice: `$${item.price.toFixed(2)}`,
       inStock: item.quantity > 0
     };
      })
    }}
  2. Finding specific items:

    {{ 
      $json.products.filter(product => 
     product.category === 'electronics' && 
     product.price < 1000
      )
    }}
  3. Calculating totals:

    {{ 
      $json.orderItems.reduce((sum, item) => sum + (item.price \* item.quantity), 0).toFixed(2)
    }}

 

Conclusion

 

Expressions in n8n are extremely powerful and flexible, allowing you to create dynamic workflows that can adapt to different data and conditions. By mastering expressions, you'll be able to create more sophisticated automation without needing to rely as heavily on Function nodes or external code. Start with simple expressions and gradually build up to more complex ones as you become more comfortable with the syntax and capabilities.

Want to explore opportunities to work with us?

Connect with our team to unlock the full potential of no-code solutions with a no-commitment consultation!

Book a Free Consultation

Client trust and success are our top priorities

When it comes to serving you, we sweat the little things. That’s why our work makes a big impact.

Rapid Dev was an exceptional project management organization and the best development collaborators I've had the pleasure of working with. They do complex work on extremely fast timelines and effectively manage the testing and pre-launch process to deliver the best possible product. I'm extremely impressed with their execution ability.

CPO, Praction - Arkady Sokolov

May 2, 2023

Working with Matt was comparable to having another co-founder on the team, but without the commitment or cost. He has a strategic mindset and willing to change the scope of the project in real time based on the needs of the client. A true strategic thought partner!

Co-Founder, Arc - Donald Muir

Dec 27, 2022

Rapid Dev are 10/10, excellent communicators - the best I've ever encountered in the tech dev space. They always go the extra mile, they genuinely care, they respond quickly, they're flexible, adaptable and their enthusiasm is amazing.

Co-CEO, Grantify - Mat Westergreen-Thorne

Oct 15, 2022

Rapid Dev is an excellent developer for no-code and low-code solutions.
We’ve had great success since launching the platform in November 2023. In a few months, we’ve gained over 1,000 new active users. We’ve also secured several dozen bookings on the platform and seen about 70% new user month-over-month growth since the launch.

Co-Founder, Church Real Estate Marketplace - Emmanuel Brown

May 1, 2024 

Matt’s dedication to executing our vision and his commitment to the project deadline were impressive. 
This was such a specific project, and Matt really delivered. We worked with a really fast turnaround, and he always delivered. The site was a perfect prop for us!

Production Manager, Media Production Company - Samantha Fekete

Sep 23, 2022