Contents

n8n Expressions Cheat-Sheet

Current version: 1.0
Published on: June 06, 2025

This guide provides a detailed overview of n8n expressions, covering everything from basic variable access to advanced data transformations. The cheat sheet is organized by skill level to help you master JavaScript expressions in n8n workflows.

Table of Contents

Intro

  1. What are n8n expressions?
  2. How and when to use them
  3. Quick Reference
  4. Learning resources

n8n Workflow Templates Analysis

  1. Beginner Level
  2. Novice Level
  3. Intermediate Level
  4. Expert Level

What are n8n expressions?

n8n expressions are short JavaScript code snippets within {{ }} brackets that provide dynamic capabilities. They allow you to access and transform data from previous nodes, the workflow context, and your n8n environment.

Expressions rely on Tournament - n8n’s templating language, extended with custom methods, variables, and data transformation functions. You can execute JavaScript snippets within expressions without using a separate Code Node.

Basic syntax: {{ your JavaScript expression here }}

n8n expression example

Expressions are available in every n8n node in the majority of input fields (including configuration fields)

Key Capabilities

How and when to use them

Use Case Description
Simplify IF conditions Replace complex IF nodes with inline ternary operator for simple conditional logic.
Conditional logic Use logical operators for quick decisions within existing nodes.
Smart parametrization Create dynamic endpoints, filenames, and parameters based on data from previous nodes.
Data transformation Format, calculate, and manipulate data on-the-fly without separate transformation nodes.
Array/object operations Transform data structures using JavaScript array methods and n8n’s built-in transformation functions.
Date and time manipulation Leverage Luxon integration for sophisticated date operations.

Quick Reference

Here’s a very brief summary for the most common expressions. Curly {{ }} brackets were removed for simplicity.

Category Expression Description Use Case
Current Data $json Current item JSON data Access current data
  $json.fieldName Specific field from current item Get specific property
  $itemIndex Current item index (0-based) Loop processing
  $binary Current item binary data File/image operations
Node Access $("NodeName").first() First item from named node Get single result
  $("NodeName").all() All items from named node Process multiple items
  $("NodeName").last() Last item from named node Get latest item
  $("NodeName").item Linked item from named node Trace data lineage
Date/Time $now Current timestamp Timestamps
  $today Today at midnight Date operations
  $now.toFormat("yyyy-MM-dd") Format date as string Date formatting
  $now.plus({days: 7}) Add 7 days to current date Date calculations
Conditionals condition ? "yes" : "no" Ternary operator Simple conditions
  value ?? "default" Null coalescing operator Handle null values
  $if(condition, "true", "false") n8n if helper function Complex conditions
  value \|\| "fallback" Logical OR fallback Default values
String Methods text.toUpperCase() Convert to uppercase Text formatting
  text.toLowerCase() Convert to lowercase Text formatting
  text.includes("search") Check if text contains substring Text validation
  text.extractEmail() Extract email from text Data extraction
Array Methods array.length Get array length Count items
  array.filter(x => x > 5) Filter array items Data filtering
  array.map(x => x.name) Transform array items Data transformation
  array.join(", ") Join array to string Text generation
Utility $execution.id Current execution ID Workflow tracking
  $prevNode.name Previous node name Flow control
  $runIndex Current run index Loop counting
  $vars.variableName Access custom variable Configuration

Learning resources

n8n Community Templates Analysis

Overview

This comprehensive guide analyzes 3,224 expressions from 830 unique community workflows, categorizing them by usage patterns and complexity. Each category includes actual expressions used in production workflows.

Methodology

Initial analysis was conducted in three phases:

  1. Data was ingested on 20th of May 2025. Template JSONs were analyzed via regular expressions. 1642 workflow templates had ANY JS expressions. 3200+ real-world expressions were extracted from 830 templates.
  2. Raw data was analyzed with Google Gemini 2.5 Pro to categorize expressions into several groups and provide references to the original templates.
  3. Final report was compiled from intermediary summaries + raw data via Perplexity Labs.

Beginner Level

This section covers the fundamental patterns. Master these before moving to novice-level expressions


1. Basic Property Access and String Manipulation

Overview: The most common pattern in n8n - accessing properties of the $json object and applying basic JavaScript string methods like trim(), concatenation (+), and replace(). This is essential for cleaning up data, combining fields, or making simple text substitutions.

Basic Property Access

// Access simple properties
{{$json.name}}
{{$json.email}}
{{$json.status}}

// Access nested properties
{{$json.user.firstName}}
{{$json.data.results}}
{{$json.settings.config}}

String Cleaning and Formatting

// Remove whitespace
{{$json.text.trim()}}

// Basic string concatenation
{{$json.title + $json.description}}
{{$json.firstName + " " + $json.lastName}}

// Simple text replacement
{{$json.topic.replace('"','')}}
{{$json.content.replace('old text', 'new text')}}

// Case conversion
{{$json.name.toLowerCase()}}
{{$json.title.toUpperCase()}}

2. Working with JSON Strings

Overview: Converting JavaScript objects or parts of objects into JSON strings using toJsonString(). This is often necessary when passing data between nodes or when a node expects a string representation of an object.

Basic JSON Conversion

// Convert entire object to JSON string; equivalent to JSON.stringify()
{{$json.toJsonString()}}

// Convert specific properties to JSON string
{{$json.tools.toJsonString()}}
{{$json.config.toJsonString()}}
{{$json.data.toJsonString()}}

JSON with String Manipulation

// JSON conversion with quote replacement
{{$json.toJsonString().replaceAll(/'/g,"''")}}

// Convert and format JSON
{{$json.categories.toJsonString()}}
{{$json.settings.toJsonString().trim()}}

3. Checking for Existence and Null Values

Overview: Using comparison operators (!== null, == null) to check if a property exists and is not null. This is a simple way to determine if a specific piece of data is available before trying to use it.

Basic Existence Checks

// Check if property is not null
{{$json.twitter.id !== null}}
{{$json.email !== null}}
{{$json.data !== null}}

// Check if property is null
{{$json.waiting_reply != null}}
{{$json.optional_field == null}}

Boolean Conversion for Existence

// Convert to boolean (double negation)
{{!!$json.value}}
{{!!$json.data}}
{{!!$json.settings}}

// Check object properties exist
{{!!$json.user.email}}
{{!!$json.config.enabled}}

4. Checking Boolean Conditions

Overview: Directly checking if a property’s value is equal to a specific boolean value or string representation of a boolean. Essential for conditional logic and workflow branching.

Simple Boolean Checks

// String equality checks
{{$json.Action === "approve"}}
{{$json.status === "active"}}
{{$json.type === "premium"}}

// Boolean value checks
{{$json.enabled === true}}
{{$json.verified === false}}
{{$json.public === true}}

Status and Type Verification

// Check action types
{{$json.operation === "create"}}
{{$json.method === "POST"}}
{{$json.mode === "production"}}

// Verify boolean flags
{{$json.isActive === true}}
{{$json.hasPermission === true}}
{{$json.isComplete === false}}

5. Node Data Access from Previous Workflow Steps

Overview: The $('Node Name') syntax is a common pattern for accessing data processed by earlier nodes in your workflow. While very useful, this pattern obscures data flow visibility within the workflow. Do not overuse this approach. One good suggestion is to use fixed CONFIG Set node in the beginning of the workflow and intelligent use of Merge nodes. This way the data is almost always accessible from the previous nodes and in rare cases only CONFIG node is referenced.

Basic Node Access Patterns

// Access first item from a node
{{$('Node Name').first().json.property}}
{{$('Get Data').first().json.result}}
{{$('API Call').first().json.response}}

// Access last item from a node
{{$('Process Data').last().json.output}}
{{$('Transform').last().json.final}}

// Access current item in loops
{{$('Split Data').item.json.value}}
{{$('Each Item').item.json.field}}

Common Node Access Patterns

// Get configuration from setup nodes
{{$('Get Config').first().json.apiKey}}
{{$('Setup').first().json.endpoint}}
{{$('Initialize').first().json.settings}}

// Access processed data from previous steps
{{$('Clean Data').first().json.cleaned}}
{{$('Transform').first().json.formatted}}
{{$('Validate').first().json.verified}}

Common Beginner Patterns Summary

Best Practices for Beginners

  • Use .first() when you expect a single item from a previous node or when the item linking between nodes could be broken.
  • Use trim() to clean up user input and API responses
  • Check for null values before performing operations on optional data
  • Use clear, descriptive node names for better expression readability
  • Start with simple property access before moving to complex transformations

Common Mistakes to Avoid

  • Forgetting to use .json when accessing node data
  • Not checking for null values before string operations
  • Using complex expressions when simple property access would work
  • Mixing up === (strict equality) with == (loose equality)

Novice Level

This section builds upon basic property access with conditional logic, data fallbacks, string processing, and simple transformations. These patterns represent the next step in n8n mastery.


1. Conditional Logic and Default Values

Overview: Using the logical OR operator (||) and ternary operators to provide fallback values when properties are null, undefined, or empty. This is essential for handling missing data and ensuring workflows don’t break with incomplete inputs.

Basic Default Values with OR Operator

// Provide fallback values
{{$json.textHtml || $json.textPlain}}
{{$json.title || "Untitled"}}

// Numeric defaults
{{$json.tries || 0}}
{{$json.maxLimit || 100}}

// Configuration defaults
{{$json.language || 'en'}}
{{$json.theme || 'light'}}

Ternary Operators for Conditional Logic

// Simple condition checks
{{$json.status === 'active' ? 'Online' : 'Offline'}}
{{$json.age >= 18 ? 'Adult' : 'Minor'}}
{{$json.verified ? 'Verified User' : 'Unverified'}}

// Complex conditional logic
{{$json.value.isEmpty() ? $json.id : $json.value[0].id}}
{{$json.type === 'premium' ? $json.premiumFeatures : $json.basicFeatures}}

Boolean Logic Combinations

// AND conditions
{{$json.type == 'audio' && Boolean($json.audio)}}
{{$json.enabled && $json.verified && $json.active}}

// OR conditions
{{$json.email || $json.alternateEmail || 'no-email@example.com'}}
{{$json.firstName || $json.username || 'Anonymous'}}

2. String Splitting and Substring Operations

Overview: Breaking down strings into smaller parts using split() or extracting portions using substring(). This is crucial for parsing delimited data, extracting domains from URLs, and processing structured text.

String Splitting Patterns

// Split by delimiter and take specific part
{{$json.title.split('(Severity:')[1].replace(')', '').trim()}}
{{$json.email.split('@')[1]}}  // Get domain from email
{{$json.fullName.split(' ')[0]}}  // Get first name

// URL parsing with split
{{$json.url.split('://')[1].split('/')[0]}}  // Extract domain
{{$json.path.split('/').pop()}}  // Get filename from path

Substring Extraction

// Extract fixed-length portions
{{$json.title.substring(14)}}
{{$json.id.substring(0, 8)}}  // First 8 characters
{{$json.description.substring(10, 50)}}  // Characters 10-50

// Combined with other operations
{{$json.code.substring(0, 3).toUpperCase()}}
{{$json.text.substring(5).trim()}}

Chain Operations for Complex Processing

// Multi-step string processing
{{$json.title.split('(Severity:')[1].replace(')', '').trim()}}
{{$json.filename.split('.')[0].toLowerCase()}}
{{$json.url.split('://')[1].split('/')[0].toLowerCase()}}

3. Type Conversion and Date Manipulation

Overview: Converting between data types and working with dates using toDateTime(), Number(), and other conversion methods. Essential for API integrations and data formatting.

Date Conversion and Formatting

// Convert to date and extract parts
{{$json.release_date.toDateTime().year}}
{{$json.timestamp.toDateTime().month}}
{{$json.createdAt.toDateTime().day}}

// Format dates
{{$json.eventDate.toDateTime().toISOString()}}
{{$json.birthday.toDateTime().toFormat('yyyy-MM-dd')}}

Number Conversion

// Convert strings to numbers
{{Number($json.price)}}
{{parseInt($json.quantity)}}
{{parseFloat($json.percentage)}}

// Conditional number conversion
{{$json?.query?.maxlimit == null ? 70000 : Number($json?.query?.maxlimit)}}
{{isNaN(Number($json.value)) ? 0 : Number($json.value)}}

Arithmetic Operations

// Simple math operations
{{$json.waitSeconds + 60}}
{{$json.price * $json.quantity}}
{{$json.total - $json.discount}}

// Percentage calculations
{{($json.completed / $json.total) * 100}}
{{Math.round($json.average * 100) / 100}}

4. Accessing Data from Previous Nodes

Overview: Advanced patterns for referencing data processed in earlier workflow steps, including dynamic property access and node data integration with current item processing.

Dynamic Node Data Access

// Access node data with dynamic property names
{{$json[$('Setup').first().json.domainCustomFieldId2]}}
{{$json[$('Config').first().json.fieldName]}}

// Conditional node access
{{$('Node').isExecuted ? $('Node').first().json.value : 'default'}}
{{$('API Call').all().length > 0 ? $('API Call').first().json.data : null}}

Node Data Integration with String Operations

// Replace text using node data
{{$json.Transfers.from_address.replace($('Edit Fields').item.json['Your Wallet Address'],"Your Wallet Address")}}
{{$json.template.replace('{{placeholder}}', $('Variables').first().json.value)}}

// Combine node data with current data
{{$('User Info').first().json.name + ': ' + $json.message}}
{{$json.prefix + $('Settings').first().json.suffix}}

Error Handling with Node Access

// Safe node access with fallbacks
{{$('Data Source').first()?.json?.result || 'No data'}}
{{$('API').isExecuted && $('API').first().json ? $('API').first().json.value : null}}

5. Optional Chaining and Nullish Coalescing

Overview: Using the optional chaining operator (?.) and nullish coalescing operator (??) to safely access nested properties and provide defaults. This prevents errors when dealing with potentially missing or undefined data.

Safe Property Access

// Basic optional chaining
{{$json?.user?.email}}
{{$json?.settings?.theme}}

// With fallback values
{{$json?.user?.name || "Anonymous"}}
{{$json?.config?.timeout ?? 30}}
{{$json?.response?.data?.items || []}}

Complex Nested Access

// Deep property access with safety
{{$json?.data?.match(/<body[^>]*>([\s\S]*?)<\/body>/i)?.[1]}}
{{$json?.parameters?.model?.value || $json?.parameters?.model || $json?.parameters?.modelId?.cachedResultName}}

// Array and object safety
{{$json?.results?.[0]?.name}}
{{$json?.user?.preferences?.notifications?.email}}

Multiple Fallback Chains

// Cascade through multiple potential sources
{{$json?.primaryEmail || $json?.secondaryEmail || $json?.backupContact?.email || "no-email"}}
{{$json?.title?.en || $json?.title?.default || $json?.name || "Untitled"}}

// Type-safe operations
{{$json?.count ? $json.count + 1 : 1}}
{{$json?.items?.length ? $json.items.join(', ') : 'No items'}}

6. String Processing

Overview: More sophisticated string operations including regular expressions, complex replacements, and multi-step text transformations commonly used in data cleaning and formatting.

Multi-step String Cleaning

// Chain multiple string operations
{{$json.text.trim().toLowerCase().replace(/\s+/g, '-')}}
{{$json.title.replace(/[^\w\s]/g, '').trim().substring(0, 50)}}

// Remove and replace patterns
{{$json.content.replace(/\n/g, ' ').replace(/\s+/g, ' ').trim()}}
{{$json.filename.replace(/[<>:"/\\|?*]/g, '_').toLowerCase()}}

Email and URL Processing

// Extract domains and validate
{{$json.email.split('@')[1].toLowerCase()}}
{{$json.url.includes('https://') ? $json.url : 'https://' + $json.url}}

// Clean and format URLs
{{$json.website.replace(/^https?:\/\//, '').replace(/\/$/, '')}}
{{$json.domain.startsWith('www.') ? $json.domain.substring(4) : $json.domain}}

Text Validation and Formatting

// Length validation with truncation
{{$json.description.length > 100 ? $json.description.substring(0, 97) + '...' : $json.description}}
{{$json.title.length < 5 ? $json.title + ' (short title)' : $json.title}}

// Format validation
{{$json.phone.replace(/\D/g, '').length === 10 ? $json.phone : 'Invalid phone'}}
{{$json.email.includes('@') && $json.email.includes('.') ? $json.email : 'Invalid email'}}

Common Novice Patterns Summary

Best Practices for Novice Level

  • Always provide fallback values for optional data
  • Use optional chaining (?.) when accessing nested properties
  • Validate data types before conversion operations
  • Chain string operations logically from left to right
  • Test expressions with both complete and incomplete data

Common Mistakes to Avoid

  • Forgetting fallback values when using logical OR (||)
  • Not handling null/undefined values in nested access
  • Mixing up ?? (nullish coalescing) with || (logical OR)
  • Over-complicating string operations instead of using multiple steps
  • Not validating data before type conversion

Intermediate Level

This section covers intermediate-level n8n expression patterns that introduce more complex data manipulation techniques. These expressions often combine multiple operations, utilize advanced JavaScript methods, and solve specific data transformation challenges


1. Array Manipulation and Transformation

Overview: Working with arrays in the $json object using JavaScript array methods like join(), map(), filter(), and more. These patterns are essential for transforming collections of data and restructuring complex information.

Array Joining Operations

// Join array elements with separators
{{$json.topics.join('\n')}}
{{$json.tags.join(', ')}}
{{$json.items.join(' | ')}}

// Join with formatting
{{$json.names.map(n => n.toUpperCase()).join(' - ')}}

Array Mapping and Transformation

// Transform each array element
{{$json.items.map(item => item.name)}}
{{$json.users.map(user => user.firstName + ' ' + user.lastName)}}

// Combine mapping with filtering
{{$json.products.filter(p => p.inStock).map(p => p.name)}}
{{$json.emails.filter(e => e.includes('@gmail.com')).length}}

Array Extraction

// Extract and transform nested array data
{{$json.trend_scores.map(item => item.score).join("; ")}}
{{$json.attendees.map(person => person.name).join(', ')}}
{{$json.results.map(r => `${r.name}: ${r.score}`).join('\n')}}

2. Regular Expressions for Pattern Matching

Overview: Using regular expressions with string methods like match() and replace() to extract specific patterns from text. This is powerful for parsing structured content like emails, dates, URLs, or cleaning data based on complex pattern-matching rules. Regular expressions are a broad topic - refer to MDN’s regex guide for comprehensive coverage.

Basic Pattern Matching

// Extract specific patterns
{{$json.email.match(/([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)/)[0]}}
{{$json.text.match(/\d{4}-\d{2}-\d{2}/)[0]}}  // Extract date YYYY-MM-DD

// Capture groups with regex
{{$json.title.match(/[^ ]* ([^:]*):/)[1].trim()}}
{{$json.URL.match(/(@[^\\/?]+)/)[1]}}

3. String and Data Transformations

Overview: Complex manipulations combining multiple JavaScript methods, often involving string transformations, conditional logic, and object manipulation. These expressions represent the more sophisticated data processing in n8n workflows.

Multi-step String Processing

// Multiple string operations chained
{{$json.title.split('Severity:')[1].replaceAll(')', '').trim().toLowerCase().toTitleCase()}}
{{$json.user_prompt.replace(/\n/g, " ").replace(/\s+/g, " ").trim()}}
{{$json.name.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '')}}

// Advanced text normalization
{{$json.content.normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase()}}
{{$json.tags.map(tag => tag.trim().toLowerCase()).filter(Boolean).join(',')}}

Conditional String Transformations

// Complex conditional string logic
{{$json.value.toLowerCase().includes('dkim=pass') ? "pass" : $json.value.toLowerCase().includes('dkim=fail') ? "fail" : $json.value.toLowerCase().includes('dkim=temperror') ? "error" : "unknown"}}
{{$json.virusTotalStats.suspicious + $json.virusTotalStats.malicious === 0 ? "✅ Harmless": "🚨 Malicous"}}

4. Array Operations

Overview: Array manipulation techniques including filtering, mapping, reducing, and custom sorting. These patterns enable complex data transformation and aggregation operations essential for reporting and data processing.

Custom Sorting and Array Transformations

// Sort arrays by property
{{$json.items.sort((a, b) => a.name.localeCompare(b.name))}}
{{$json.products.sort((a, b) => b.price - a.price)}}

// Get unique values
{{[...new Set($json.categories)]}}
{{$json.tags.filter((tag, index, array) => array.indexOf(tag) === index)}}

5. JSON Object Property Manipulation

Overview: Working with complex object structures using JavaScript object methods like Object.keys(), Object.values(), and Object.entries(). These patterns enable dynamic property access, configuration handling, object introspection, and restructuring of complex data objects into more usable formats.

Object Property Operations

// Get object keys and values
{{Object.keys($json.data)}}
{{Object.values($json.stats)}}
{{Object.entries($json.config).map(([key, value]) => `${key}: ${value}`).join('\n')}}

// Check property existence
{{Object.keys($json.user).includes('email')}}
{{Object.keys($json.settings).length > 0}}
{{$json.hasOwnProperty('config')}}

6. Data Validation

Overview: Advanced patterns for validating data integrity, handling edge cases, and preventing errors in workflows. These expressions use type checking, format validation, and safe conversion techniques to create automations that gracefully handle unexpected or malformed data inputs.

Data Validation

// Validate email format
{{/^[\w-\.]+@([\w-]+\.)+[\w-]{2,}$/.test($json.email) ? $json.email : 'Invalid email'}}

// Number validation
{{!isNaN(Number($json.price)) && Number($json.price) > 0 ? Number($json.price) : null}}

// String length and content validation
{{$json.password && $json.password.length >= 8 ? true : 'Password too short'}}

Type Checking and Conversion

// Type-safe operations
{{typeof $json.count === 'number' ? $json.count : 0}}
{{Array.isArray($json.items) ? $json.items : [$json.items].filter(Boolean)}}
{{typeof $json.enabled === 'boolean' ? $json.enabled : $json.enabled === 'true'}}

// Safe array operations
{{(Array.isArray($json.tags) ? $json.tags : [$json.tags]).filter(Boolean).join(', ')}}
{{$json.results?.length ? $json.results : []}}

Common Intermediate Patterns Summary

Best Practices for Intermediate Level

  • Break complex transformations into steps for better readability
  • Validate data existence before performing complex operations
  • Use consistent chaining patterns for method sequences
  • Add comments for complex regex patterns
  • Test expressions with both normal and edge cases

Common Mistakes to Avoid

  • Forgetting array bounds when accessing array indices
  • Missing error handling for regex that might not match
  • Creating overly complex chains that are hard to debug
  • Assuming object properties always exist
  • Not considering empty array or object cases

Expert Level

This section covers the most sophisticated n8n expression patterns involving complex JavaScript logic, advanced data transformations, and dynamic code generation. These patterns enable highly customized automation solutions.


1. Advanced Array Transformations with Reduce and FlatMap

Overview: Using advanced JavaScript array methods like reduce() for complex aggregations and data restructuring, flatMap() for mapping and flattening nested structures, and complex method chaining for sophisticated data analysis and transformation operations.

Using Reduce for Aggregation and Object Transformation

// Transform array of objects into a single keyed object
{{$json.data.reduce((acc, { id, name }) => ({ ...acc, [id]: name }), {})}}

// Calculate aggregated statistics from multiple data points
{{$input.all().map(x => x.json.Data.DownloadLink).reduce((accumulator, currentValue) => accumulator && currentValue, true)}}

// Parse query strings into structured objects
{{$json.query.substring($json.query.indexOf('?') + 1).split('&').reduce((result, item) => (result[item.split('=')[0]] = decodeURIComponent(item.split('=')[1]), result), {})}}

Using FlatMap for Complex Restructuring

// Flatten nested array structures after transformation
{{$json.recipe.tags.flatMap(tag => tag.preferences)}}

// Process hierarchical data with recursive-like flattening
{{$json.children.flatMap(item => [{ id: item.id, name: item.name }, ...item.children.flatMap(child => [child])])}}

// Aggregate data across multiple workflow runs
{{Array($runIndex+1).fill(0).flatMap((_,idx) => { 
  try { 
    return $('Generate Data').all(0,idx).flatMap(item => item.json.results) 
  } catch (e) { 
    return [] 
  } 
})}}

Complex Method Chaining

// Chain multiple operations for data discovery
{{$input.all().map(item => item.json).find(item => item.id === $('Config').first().json.tableId).fields.find(field => field.name === $('Config').first().json.inputField)}}

// Multi-step text parsing with chained transformations
{{$json.text
  .substring($json.text.search(/Section\./), $json.text.length)
  .split(/Section\./g)
  .filter(text => !text.isEmpty())
  .map(text => ({
    title: text.substring(0, text.indexOf('.')),
    content: text.substring(text.indexOf('.')+1).replaceAll('\n', ' ').trim()
  }))
}}

2. Immediately Invoked Function Expressions (IIFEs)

Overview: Encapsulating complex multi-step logic, variable declarations, error handling, and conditional flows within (() => { ... })() functions. This enables creating sophisticated mini-programs directly within expression fields for complex data processing scenarios.

IIFEs for Error Handling and Safe Data Access

// Safely access data from multiple potential sources
{{(() => {
    try { return $('variables').item.json.spotify_playlist_id } catch(e) {}
    try { return $('variables2').item.json.spotify_playlist_id } catch(e) {}
    return undefined;
})()}}

// Complex date parsing with validation
{{(() => {
    const rawDate = $json.body['11'];
    if (!rawDate || typeof rawDate !== 'string') return '';
    const [datePart, timePart] = rawDate.split(' ');
    if (!datePart || !timePart) return '';
    const [year, month, day] = datePart.split('-');
    if (!year || !month || !day || year.length !== 4) return '';
    const isoDateTime = `${year}-${month}-${day}T${timePart}:00+01:00`;
    return Math.floor(new Date(isoDateTime).getTime() / 1000);
})()}}

IIFEs for Dynamic Content Generation

// Generate visual progress indicators
{{(function() {
    let p = $json.sum_value / $json.target;
    let n = Math.round(p * 10);
    n = Math.max(0, Math.min(10, n));
    return '💧'.repeat(n) + ''.repeat(10 - n);
})()}}

// Complex HTML generation with data processing
{{(function(items) {
  const grouped = items.reduce((acc, item) => {
    acc[item.category] = acc[item.category] || [];
    acc[item.category].push(item);
    return acc;
  }, {});
  
  return Object.keys(grouped).map(category => 
    `<div class="category">${category}: ${grouped[category].length} items</div>`
  ).join('');
})(
  $input.all().map(item => item.json).filter(item => item.category)
)}}

3. Advanced JMESPath Integration

Overview: Leveraging JMESPath for sophisticated JSON querying combined with JavaScript operations for complex data extraction, aggregation, and transformation. JMESPath provides declarative querying capabilities that complement JavaScript’s procedural approach.

JMESPath with JavaScript Aggregation

// Calculate comprehensive statistics using JMESPath filtering
{{{ 
  global_total: $input.all().length,
  global_active: $jmespath($input.all(),'[?json.wf_stats.wf_active == `true`]').length,
  global_trigger: $jmespath($input.all(),'[].json.wf_trigcount').reduce((accumulator, currentValue) => accumulator + currentValue, 0) 
}}}

// Extract and format unique values as structured output
{{[...new Set($jmespath($input.all(),'[].json.tags[].name'))].map(tag => `- [${tag}](tag-${encodeURIComponent(tag)})`).join('\n')}}

Complex JMESPath Queries with Post-Processing

// Extract node types and process for analysis
{{{ 
  nodes_unique: [...new Set($jmespath($json,'nodes[*].type').map(item => item.split('.').pop().toUpperCase()))],
  nodes_count: $jmespath($json,'nodes[*].type').length,
  trigger_nodes: $jmespath($json,'nodes[?type == `n8n-nodes-base.manualTrigger`]').length
}}}

// Filter and transform complex nested structures
{{$jmespath($input.all(), '[].json.data[?status == `active` && priority > `5`].{name: name, score: metrics.performance}')}}

4. Dynamic Code and Configuration Generation

Overview: Expressions that dynamically generate code snippets, SQL queries, JSON schemas, HTML templates, or complex configurations based on runtime data. This enables highly adaptive workflows that can modify their behavior based on input characteristics.

Dynamic SQL Query Construction

// Generate parameterized SQL WHERE clauses
{{$json.where && Object.keys($json.where).length > 0
  ? `WHERE ` + Object.keys($json.where).map((key,idx) => `${key} = $${idx+1}`).join(' AND ')
  : ''
}}

// Build complex SELECT statements with dynamic columns
{{`SELECT ${$json.columns.join(', ')} FROM ${$json.table}` + 
  ($json.conditions ? ` WHERE ${Object.entries($json.conditions).map(([k,v]) => `${k} = '${v}'`).join(' AND ')}` : '')
}}

Dynamic JSON Schema Generation

// Generate JSON schema for API validation
{{(function(node) {
  if (!node) return {};
  const inputs = node.parameters.workflowInputs.values;
  return {
    "type": "object",
    "required": inputs.map(input => input.name),
    "properties": inputs.reduce((acc, input) => ({
      ...acc,
      [input.name]: { type: input.type ?? 'string' }
    }), {})
  }
})(
  $json.nodes.filter(node => node.type === 'n8n-nodes-base.executeWorkflowTrigger').first()
).toJsonString()}}

Dynamic Template Generation

// Generate complex API payloads with conditional structure
{{JSON.stringify({
  "contents": [{
    "role": "user", 
    "parts": [
      { "text": $json.meta_prompt },
      ...(($json.file_url) ? [{ "file_data": { "file_uri": $json.file_url }}] : [])
    ]
  }],
  "generationConfig": Object.fromEntries(
    Object.entries($json.config || {}).filter(([k,v]) => v !== null)
  ),
  "model": $json.model || "default-model"
})}}

// Generate HTML templates with dynamic styling
{{$json.data
  .map(item => `
    <div style="display:flex;margin-bottom:16px;${item.priority === 'high' ? 'border-left:3px solid red;' : ''}">
      <div style="width:60px;color:#ccc;">${DateTime.fromISO(item.timestamp).format('MMM dd')}</div>
      <div style="width:100%">
        <div style="font-weight:${item.urgent ? 'bold' : 'normal'};">${item.title}</div>
        <div style="color:#666;">${item.description}</div>
      </div>
    </div>
  `)
  .join('\n')
}}

5. Complex Regular Expressions and Parsing

Overview: Employing sophisticated regular expressions for specialized data extraction, validation, and transformation tasks. These patterns often combine regex with multi-step string processing for handling complex, structured, or semi-structured text data.

Advanced Pattern Extraction

// Extract duration from ISO 8601 format and convert to milliseconds
{{$json.contentDetails.duration.match(/(\d+)(?=[MHS])/g).reduce((acc, time, i) => acc + time * [60000, 1000, 1][i], 0)}}

// Parse and validate complex data formats
{{$json.text.match(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/i)?.[0] || 'No email found'}}
{{$json.content.match(/\bphone:\s*(\+?\d[\d\s-]{8,}\d)\b/i)?.[1] || 'No phone found'}}

Multi-Step Text Processing with Regex

// Complex document parsing with multiple regex operations
{{$json.document
  .replace(/<!--[\s\S]*?-->/g, '')  // Remove comments
  .replace(/<script[\s\S]*?<\/script>/gi, '')  // Remove scripts
  .match(/<body[^>]*>([\s\S]*?)<\/body>/i)?.[1]  // Extract body content
  ?.replace(/<[^>]*>/g, '')  // Remove HTML tags
  ?.replace(/\s+/g, ' ')  // Normalize whitespace
  ?.trim()
}}

// Extract structured data from formatted text
{{$json.logEntry
  .match(/\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] (\w+): (.+)/)?
  .slice(1)  // Remove full match, keep groups
  ?.reduce((obj, val, idx) => ({
    ...obj,
    [['timestamp', 'level', 'message'][idx]]: val
  }), {})
}}

6. Error Handling and Robust Data Processing

Overview: Advanced patterns for building fault-tolerant expressions that gracefully handle edge cases, missing data, and unexpected input formats. These techniques ensure workflows remain stable and continue processing even when encountering problematic data.

Comprehensive Error Handling

// Multi-level fallback with error recovery
{{(() => {
  try {
    const data = $json.response?.data?.results;
    if (!Array.isArray(data)) throw new Error('Invalid data format');
    return data.filter(item => item.status === 'active').length;
  } catch (e) {
    try {
      return $json.fallback?.count || 0;
    } catch (e2) {
      return 0;
    }
  }
})()}}

// Safe deep property access with validation
{{(() => {
  const path = ['user', 'profile', 'settings', 'notifications'];
  let current = $json;
  for (const key of path) {
    if (!current || typeof current !== 'object' || !(key in current)) {
      return null;
    }
    current = current[key];
  }
  return current;
})()}}

Type-Safe Data Processing

// Robust array processing with type checking
{{(() => {
  const items = $json.items;
  if (!Array.isArray(items)) {
    return typeof items === 'object' && items !== null ? [items] : [];
  }
  return items.filter(item => 
    item && 
    typeof item === 'object' && 
    typeof item.id !== 'undefined'
  );
})()}}

// Safe numeric operations with validation
{{(() => {
  const values = [$json.price, $json.tax, $json.shipping]
    .map(v => parseFloat(v))
    .filter(v => !isNaN(v) && isFinite(v));
  
  return values.length > 0 
    ? values.reduce((sum, val) => sum + val, 0).toFixed(2)
    : '0.00';
})()}}

Common Expert Patterns Summary

Best Practices for Expert Level

  • Encapsulate Complex Logic: Use IIFEs to group related operations and manage variable scope
  • Document Complex Expressions: Use comments within IIFEs to explain non-obvious logic
  • Implement Robust Error Handling: Always account for missing data, type mismatches, and edge cases
  • Leverage JMESPath: Combine JMESPath querying with JavaScript for efficient data processing
  • Test Thoroughly: Validate expressions with diverse input data including edge cases

Common Mistakes to Avoid

  • Over-Engineering: Don’t use complex patterns when simpler solutions suffice
  • Performance Neglect: Be mindful of expression complexity in high-volume workflows
  • Poor Error Handling: Provide fallbacks for potentially failing operations
  • Readability Sacrifice: Maintain code clarity even in sophisticated expressions
  • Side Effects: Avoid modifying external state within expressions (use Set or Code nodes instead)

Found an error or want to suggest an update? Please raise an issue or make a pull request in the n8narena GitHub repository

What’s next?

Learn how to self-host n8n

Click here to see what’s included