Comprehensive skill for n8n workflow automation including: - Workflow design and node configuration - Expression writing reference (14 KB) - Comprehensive troubleshooting guide (15 KB) - Examples for common use cases - Performance optimization tips 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
719 lines
14 KiB
Markdown
719 lines
14 KiB
Markdown
# n8n Expression Reference
|
|
|
|
This guide provides comprehensive reference for writing n8n expressions.
|
|
|
|
## Table of Contents
|
|
- [Basic Syntax](#basic-syntax)
|
|
- [Accessing Data](#accessing-data)
|
|
- [String Operations](#string-operations)
|
|
- [Number Operations](#number-operations)
|
|
- [Date & Time](#date--time)
|
|
- [Array Operations](#array-operations)
|
|
- [Object Operations](#object-operations)
|
|
- [Conditional Logic](#conditional-logic)
|
|
- [JSON Operations](#json-operations)
|
|
- [Common Patterns](#common-patterns)
|
|
|
|
## Basic Syntax
|
|
|
|
n8n expressions are wrapped in double curly braces:
|
|
```
|
|
{{ expression }}
|
|
```
|
|
|
|
You can combine text with expressions:
|
|
```
|
|
Hello {{ $json.name }}, your order #{{ $json.orderId }} is ready!
|
|
```
|
|
|
|
## Accessing Data
|
|
|
|
### Current Item Data
|
|
```javascript
|
|
// Access field in current item
|
|
{{ $json.fieldName }}
|
|
|
|
// Nested fields
|
|
{{ $json.user.email }}
|
|
{{ $json.data.items[0].name }}
|
|
|
|
// Access by bracket notation
|
|
{{ $json["field-with-dashes"] }}
|
|
```
|
|
|
|
### Previous Node Data
|
|
```javascript
|
|
// Access data from a specific node
|
|
{{ $node["HTTP Request"].json.data }}
|
|
|
|
// Access by node index
|
|
{{ $("HTTP Request").item.json.result }}
|
|
|
|
// First item from previous node
|
|
{{ $node["HTTP Request"].json }}
|
|
|
|
// Specific item by index
|
|
{{ $items("HTTP Request")[0].json.field }}
|
|
```
|
|
|
|
### Input Data
|
|
```javascript
|
|
// Current input item
|
|
{{ $input.item.json.field }}
|
|
|
|
// All input items
|
|
{{ $input.all() }}
|
|
|
|
// First input item
|
|
{{ $input.first().json.field }}
|
|
|
|
// Last input item
|
|
{{ $input.last().json.field }}
|
|
```
|
|
|
|
### Binary Data
|
|
```javascript
|
|
// Access binary data
|
|
{{ $binary.data }}
|
|
|
|
// Binary data from specific node
|
|
{{ $node["Read File"].binary.data }}
|
|
```
|
|
|
|
### Workflow & Execution Data
|
|
```javascript
|
|
// Workflow ID
|
|
{{ $workflow.id }}
|
|
|
|
// Workflow name
|
|
{{ $workflow.name }}
|
|
|
|
// Execution ID
|
|
{{ $execution.id }}
|
|
|
|
// Execution mode (manual, trigger, webhook)
|
|
{{ $execution.mode }}
|
|
|
|
// Current timestamp
|
|
{{ $now }}
|
|
|
|
// Today's date at midnight
|
|
{{ $today }}
|
|
```
|
|
|
|
## String Operations
|
|
|
|
### Basic Methods
|
|
```javascript
|
|
// Convert to lowercase
|
|
{{ $json.email.toLowerCase() }}
|
|
|
|
// Convert to uppercase
|
|
{{ $json.name.toUpperCase() }}
|
|
|
|
// Trim whitespace
|
|
{{ $json.text.trim() }}
|
|
|
|
// Get length
|
|
{{ $json.message.length }}
|
|
```
|
|
|
|
### Splitting & Joining
|
|
```javascript
|
|
// Split string into array
|
|
{{ $json.email.split('@') }}
|
|
|
|
// Get specific part after split
|
|
{{ $json.email.split('@')[1] }}
|
|
|
|
// Join array into string
|
|
{{ $json.tags.join(', ') }}
|
|
```
|
|
|
|
### Search & Replace
|
|
```javascript
|
|
// Replace first occurrence
|
|
{{ $json.text.replace('old', 'new') }}
|
|
|
|
// Replace all occurrences
|
|
{{ $json.text.replaceAll('old', 'new') }}
|
|
|
|
// Check if string includes substring
|
|
{{ $json.text.includes('keyword') }}
|
|
|
|
// Check if string starts with
|
|
{{ $json.url.startsWith('https://') }}
|
|
|
|
// Check if string ends with
|
|
{{ $json.filename.endsWith('.pdf') }}
|
|
|
|
// Find position of substring
|
|
{{ $json.text.indexOf('word') }}
|
|
```
|
|
|
|
### Substring & Slicing
|
|
```javascript
|
|
// Get substring (start, length)
|
|
{{ $json.text.substring(0, 10) }}
|
|
|
|
// Slice string (start, end)
|
|
{{ $json.text.slice(0, 5) }}
|
|
|
|
// Get first character
|
|
{{ $json.name[0] }}
|
|
|
|
// Get last character
|
|
{{ $json.name[$json.name.length - 1] }}
|
|
```
|
|
|
|
### Advanced String Operations
|
|
```javascript
|
|
// Pad start with zeros
|
|
{{ $json.id.toString().padStart(5, '0') }}
|
|
|
|
// Pad end with spaces
|
|
{{ $json.text.padEnd(20, ' ') }}
|
|
|
|
// Repeat string
|
|
{{ '-'.repeat(10) }}
|
|
|
|
// Match regex
|
|
{{ $json.text.match(/\d+/) }}
|
|
|
|
// Test regex
|
|
{{ /^\d{5}$/.test($json.zipCode) }}
|
|
```
|
|
|
|
## Number Operations
|
|
|
|
### Basic Math
|
|
```javascript
|
|
// Addition
|
|
{{ $json.price + 10 }}
|
|
|
|
// Subtraction
|
|
{{ $json.total - $json.discount }}
|
|
|
|
// Multiplication
|
|
{{ $json.quantity * $json.price }}
|
|
|
|
// Division
|
|
{{ $json.total / $json.items }}
|
|
|
|
// Modulo (remainder)
|
|
{{ $json.number % 2 }}
|
|
|
|
// Exponentiation
|
|
{{ $json.base ** $json.exponent }}
|
|
```
|
|
|
|
### Parsing & Formatting
|
|
```javascript
|
|
// Parse string to integer
|
|
{{ parseInt($json.value) }}
|
|
|
|
// Parse string to float
|
|
{{ parseFloat($json.price) }}
|
|
|
|
// Round to 2 decimal places
|
|
{{ parseFloat($json.amount).toFixed(2) }}
|
|
|
|
// Round to nearest integer
|
|
{{ Math.round($json.value) }}
|
|
|
|
// Round up
|
|
{{ Math.ceil($json.value) }}
|
|
|
|
// Round down
|
|
{{ Math.floor($json.value) }}
|
|
```
|
|
|
|
### Math Functions
|
|
```javascript
|
|
// Absolute value
|
|
{{ Math.abs($json.difference) }}
|
|
|
|
// Maximum value
|
|
{{ Math.max($json.value1, $json.value2, $json.value3) }}
|
|
|
|
// Minimum value
|
|
{{ Math.min($json.value1, $json.value2, $json.value3) }}
|
|
|
|
// Random number (0-1)
|
|
{{ Math.random() }}
|
|
|
|
// Random integer (0-99)
|
|
{{ Math.floor(Math.random() * 100) }}
|
|
|
|
// Square root
|
|
{{ Math.sqrt($json.number) }}
|
|
|
|
// Power
|
|
{{ Math.pow($json.base, $json.exponent) }}
|
|
```
|
|
|
|
### Number Validation
|
|
```javascript
|
|
// Check if number
|
|
{{ !isNaN($json.value) }}
|
|
|
|
// Check if integer
|
|
{{ Number.isInteger($json.value) }}
|
|
|
|
// Check if finite
|
|
{{ isFinite($json.value) }}
|
|
```
|
|
|
|
## Date & Time
|
|
|
|
### Current Date & Time
|
|
```javascript
|
|
// Current timestamp (ISO format)
|
|
{{ $now }}
|
|
|
|
// Today at midnight
|
|
{{ $today }}
|
|
|
|
// Using DateTime (Luxon)
|
|
{{ DateTime.now().toISO() }}
|
|
|
|
// Current timestamp in milliseconds
|
|
{{ Date.now() }}
|
|
```
|
|
|
|
### Creating Dates
|
|
```javascript
|
|
// From ISO string
|
|
{{ DateTime.fromISO($json.dateString) }}
|
|
|
|
// From format
|
|
{{ DateTime.fromFormat($json.date, 'yyyy-MM-dd') }}
|
|
|
|
// From timestamp
|
|
{{ DateTime.fromMillis($json.timestamp) }}
|
|
|
|
// Specific date
|
|
{{ DateTime.fromObject({ year: 2024, month: 1, day: 15 }) }}
|
|
```
|
|
|
|
### Formatting Dates
|
|
```javascript
|
|
// ISO format
|
|
{{ DateTime.now().toISO() }}
|
|
|
|
// Custom format
|
|
{{ DateTime.now().toFormat('yyyy-MM-dd') }}
|
|
{{ DateTime.now().toFormat('dd.MM.yyyy HH:mm:ss') }}
|
|
{{ DateTime.now().toFormat('MMMM dd, yyyy') }}
|
|
|
|
// Locale-specific
|
|
{{ DateTime.now().toLocaleString(DateTime.DATE_FULL) }}
|
|
{{ DateTime.now().toLocaleString(DateTime.DATETIME_MED) }}
|
|
|
|
// Relative time
|
|
{{ DateTime.now().toRelative() }}
|
|
```
|
|
|
|
### Date Arithmetic
|
|
```javascript
|
|
// Add time
|
|
{{ DateTime.now().plus({ days: 7 }) }}
|
|
{{ DateTime.now().plus({ hours: 2, minutes: 30 }) }}
|
|
{{ DateTime.now().plus({ months: 1 }) }}
|
|
|
|
// Subtract time
|
|
{{ DateTime.now().minus({ days: 30 }) }}
|
|
{{ DateTime.now().minus({ years: 1 }) }}
|
|
|
|
// Difference between dates
|
|
{{ DateTime.now().diff(DateTime.fromISO($json.startDate), 'days').days }}
|
|
{{ DateTime.now().diff(DateTime.fromISO($json.startDate), ['years', 'months', 'days']) }}
|
|
```
|
|
|
|
### Date Components
|
|
```javascript
|
|
// Get year
|
|
{{ DateTime.now().year }}
|
|
|
|
// Get month (1-12)
|
|
{{ DateTime.now().month }}
|
|
|
|
// Get day
|
|
{{ DateTime.now().day }}
|
|
|
|
// Get hour
|
|
{{ DateTime.now().hour }}
|
|
|
|
// Get minute
|
|
{{ DateTime.now().minute }}
|
|
|
|
// Get day of week (1-7, Mon-Sun)
|
|
{{ DateTime.now().weekday }}
|
|
|
|
// Get day name
|
|
{{ DateTime.now().weekdayLong }}
|
|
|
|
// Get month name
|
|
{{ DateTime.now().monthLong }}
|
|
```
|
|
|
|
### Date Manipulation
|
|
```javascript
|
|
// Start of day
|
|
{{ DateTime.now().startOf('day') }}
|
|
|
|
// End of month
|
|
{{ DateTime.now().endOf('month') }}
|
|
|
|
// Start of week
|
|
{{ DateTime.now().startOf('week') }}
|
|
|
|
// Set specific time
|
|
{{ DateTime.now().set({ hour: 9, minute: 0, second: 0 }) }}
|
|
```
|
|
|
|
## Array Operations
|
|
|
|
### Basic Array Methods
|
|
```javascript
|
|
// Get array length
|
|
{{ $json.items.length }}
|
|
|
|
// Access element by index
|
|
{{ $json.items[0] }}
|
|
|
|
// Last element
|
|
{{ $json.items[$json.items.length - 1] }}
|
|
|
|
// Join array
|
|
{{ $json.tags.join(', ') }}
|
|
|
|
// Check if array includes value
|
|
{{ $json.items.includes('value') }}
|
|
```
|
|
|
|
### Transforming Arrays
|
|
```javascript
|
|
// Map: transform each element
|
|
{{ $json.users.map(user => user.email) }}
|
|
{{ $json.prices.map(p => parseFloat(p) * 1.2) }}
|
|
|
|
// Filter: keep elements matching condition
|
|
{{ $json.users.filter(user => user.active === true) }}
|
|
{{ $json.numbers.filter(n => n > 10) }}
|
|
|
|
// Find: get first matching element
|
|
{{ $json.users.find(user => user.id === 123) }}
|
|
|
|
// Find index
|
|
{{ $json.items.findIndex(item => item.name === 'Product') }}
|
|
|
|
// Some: check if any element matches
|
|
{{ $json.items.some(item => item.price > 100) }}
|
|
|
|
// Every: check if all elements match
|
|
{{ $json.items.every(item => item.inStock === true) }}
|
|
```
|
|
|
|
### Array Aggregation
|
|
```javascript
|
|
// Reduce: calculate sum
|
|
{{ $json.prices.reduce((sum, price) => sum + parseFloat(price), 0) }}
|
|
|
|
// Calculate average
|
|
{{ $json.numbers.reduce((sum, n) => sum + n, 0) / $json.numbers.length }}
|
|
|
|
// Find maximum
|
|
{{ Math.max(...$json.numbers) }}
|
|
|
|
// Find minimum
|
|
{{ Math.min(...$json.numbers) }}
|
|
|
|
// Count occurrences
|
|
{{ $json.items.filter(item => item.status === 'active').length }}
|
|
```
|
|
|
|
### Sorting Arrays
|
|
```javascript
|
|
// Sort numbers ascending
|
|
{{ $json.numbers.sort((a, b) => a - b) }}
|
|
|
|
// Sort numbers descending
|
|
{{ $json.numbers.sort((a, b) => b - a) }}
|
|
|
|
// Sort strings alphabetically
|
|
{{ $json.names.sort() }}
|
|
|
|
// Sort objects by property
|
|
{{ $json.users.sort((a, b) => a.name.localeCompare(b.name)) }}
|
|
```
|
|
|
|
### Array Manipulation
|
|
```javascript
|
|
// Slice: get portion of array
|
|
{{ $json.items.slice(0, 5) }}
|
|
|
|
// Concat: combine arrays
|
|
{{ $json.array1.concat($json.array2) }}
|
|
|
|
// Flat: flatten nested arrays
|
|
{{ $json.nestedArray.flat() }}
|
|
|
|
// Unique values (using Set)
|
|
{{ [...new Set($json.items)] }}
|
|
|
|
// Reverse array
|
|
{{ $json.items.reverse() }}
|
|
```
|
|
|
|
## Object Operations
|
|
|
|
### Accessing Properties
|
|
```javascript
|
|
// Dot notation
|
|
{{ $json.user.name }}
|
|
|
|
// Bracket notation
|
|
{{ $json["property-name"] }}
|
|
|
|
// Nested access
|
|
{{ $json.data.user.addresses[0].city }}
|
|
```
|
|
|
|
### Object Methods
|
|
```javascript
|
|
// Get all keys
|
|
{{ Object.keys($json) }}
|
|
|
|
// Get all values
|
|
{{ Object.values($json) }}
|
|
|
|
// Get entries (key-value pairs)
|
|
{{ Object.entries($json) }}
|
|
|
|
// Check if property exists
|
|
{{ $json.hasOwnProperty('email') }}
|
|
|
|
// Check if object has any properties
|
|
{{ Object.keys($json).length > 0 }}
|
|
```
|
|
|
|
### Object Transformation
|
|
```javascript
|
|
// Merge objects
|
|
{{ Object.assign({}, $json.obj1, $json.obj2) }}
|
|
|
|
// Spread operator
|
|
{{ {...$json.user, role: 'admin'} }}
|
|
|
|
// Extract specific properties
|
|
{{ (({ name, email }) => ({ name, email }))($json.user) }}
|
|
|
|
// Map object to array
|
|
{{ Object.entries($json).map(([key, value]) => ({ key, value })) }}
|
|
```
|
|
|
|
## Conditional Logic
|
|
|
|
### Ternary Operator
|
|
```javascript
|
|
// Basic ternary
|
|
{{ $json.status === 'active' ? 'Active' : 'Inactive' }}
|
|
|
|
// Nested ternary
|
|
{{ $json.score >= 90 ? 'A' : $json.score >= 80 ? 'B' : 'C' }}
|
|
|
|
// With numbers
|
|
{{ $json.quantity > 0 ? $json.price * $json.quantity : 0 }}
|
|
```
|
|
|
|
### If Function
|
|
```javascript
|
|
// Basic if
|
|
{{ $if($json.premium === true, 'Premium User', 'Regular User') }}
|
|
|
|
// With expressions
|
|
{{ $if($json.total > 100, $json.total * 0.9, $json.total) }}
|
|
```
|
|
|
|
### Logical Operators
|
|
```javascript
|
|
// AND
|
|
{{ $json.age >= 18 && $json.verified === true }}
|
|
|
|
// OR
|
|
{{ $json.role === 'admin' || $json.role === 'moderator' }}
|
|
|
|
// NOT
|
|
{{ !$json.deleted }}
|
|
|
|
// Nullish coalescing
|
|
{{ $json.name ?? 'Unknown' }}
|
|
|
|
// Default value
|
|
{{ $json.value || 'default' }}
|
|
```
|
|
|
|
### Comparison
|
|
```javascript
|
|
// Equality
|
|
{{ $json.status === 'completed' }}
|
|
|
|
// Inequality
|
|
{{ $json.type !== 'test' }}
|
|
|
|
// Greater than
|
|
{{ $json.score > 50 }}
|
|
|
|
// Less than or equal
|
|
{{ $json.price <= 99.99 }}
|
|
|
|
// Type checking
|
|
{{ typeof $json.value === 'string' }}
|
|
```
|
|
|
|
## JSON Operations
|
|
|
|
### Parsing & Stringifying
|
|
```javascript
|
|
// Parse JSON string
|
|
{{ JSON.parse($json.jsonString) }}
|
|
|
|
// Stringify object
|
|
{{ JSON.stringify($json.data) }}
|
|
|
|
// Stringify with formatting
|
|
{{ JSON.stringify($json.data, null, 2) }}
|
|
```
|
|
|
|
### Handling JSON Errors
|
|
```javascript
|
|
// Safe JSON parse with try/catch in Code node
|
|
try {
|
|
const data = JSON.parse(items[0].json.rawData);
|
|
return [{json: data}];
|
|
} catch (error) {
|
|
return [{json: {error: 'Invalid JSON', raw: items[0].json.rawData}}];
|
|
}
|
|
```
|
|
|
|
## Common Patterns
|
|
|
|
### Email Validation
|
|
```javascript
|
|
// Check if valid email format
|
|
{{ /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test($json.email) }}
|
|
|
|
// Extract domain from email
|
|
{{ $json.email.split('@')[1] }}
|
|
|
|
// Normalize email
|
|
{{ $json.email.toLowerCase().trim() }}
|
|
```
|
|
|
|
### URL Operations
|
|
```javascript
|
|
// Extract domain from URL
|
|
{{ new URL($json.url).hostname }}
|
|
|
|
// Get URL parameters
|
|
{{ new URL($json.url).searchParams.get('id') }}
|
|
|
|
// Build URL with parameters
|
|
{{ `https://api.example.com/users?id=${$json.userId}&format=json` }}
|
|
```
|
|
|
|
### Phone Number Formatting
|
|
```javascript
|
|
// Remove non-digits
|
|
{{ $json.phone.replace(/\D/g, '') }}
|
|
|
|
// Format US phone
|
|
{{ $json.phone.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3') }}
|
|
```
|
|
|
|
### Price/Currency Formatting
|
|
```javascript
|
|
// Format as currency
|
|
{{ parseFloat($json.price).toFixed(2) }}
|
|
|
|
// Add currency symbol
|
|
{{ `$${parseFloat($json.price).toFixed(2)}` }}
|
|
|
|
// Calculate with tax
|
|
{{ (parseFloat($json.price) * 1.19).toFixed(2) }}
|
|
```
|
|
|
|
### Name Formatting
|
|
```javascript
|
|
// Capitalize first letter
|
|
{{ $json.name.charAt(0).toUpperCase() + $json.name.slice(1).toLowerCase() }}
|
|
|
|
// Title case
|
|
{{ $json.name.split(' ').map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(' ') }}
|
|
|
|
// Initials
|
|
{{ $json.firstName[0] + $json.lastName[0] }}
|
|
```
|
|
|
|
### Generating IDs
|
|
```javascript
|
|
// Random UUID-like string
|
|
{{ Math.random().toString(36).substring(2, 15) }}
|
|
|
|
// Timestamp-based ID
|
|
{{ Date.now().toString(36) }}
|
|
|
|
// Sequential ID with padding
|
|
{{ String($json.index).padStart(6, '0') }}
|
|
```
|
|
|
|
### Data Validation
|
|
```javascript
|
|
// Check if empty
|
|
{{ !$json.value || $json.value.trim() === '' }}
|
|
|
|
// Check if valid number
|
|
{{ !isNaN(parseFloat($json.value)) }}
|
|
|
|
// Check if array has items
|
|
{{ Array.isArray($json.items) && $json.items.length > 0 }}
|
|
|
|
// Check if date is in future
|
|
{{ DateTime.fromISO($json.date) > DateTime.now() }}
|
|
```
|
|
|
|
### Data Cleaning
|
|
```javascript
|
|
// Remove duplicates from array
|
|
{{ [...new Set($json.items)] }}
|
|
|
|
// Remove null/undefined values
|
|
{{ $json.items.filter(item => item != null) }}
|
|
|
|
// Remove empty strings
|
|
{{ $json.values.filter(v => v !== '') }}
|
|
|
|
// Trim all strings in array
|
|
{{ $json.items.map(item => item.trim()) }}
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
1. **Use meaningful variable names in Code nodes**
|
|
2. **Test expressions with sample data** before deploying
|
|
3. **Handle null/undefined values** with nullish coalescing (`??`)
|
|
4. **Use Set node for simple transformations**, Code node for complex logic
|
|
5. **Break complex expressions** into multiple steps for readability
|
|
6. **Check data structure** in debug panel before writing expressions
|
|
7. **Use DateTime for dates**, not JavaScript Date (better timezone support)
|
|
8. **Validate data** before processing to avoid runtime errors
|
|
9. **Document complex expressions** with comments in Code nodes
|
|
10. **Cache frequently used values** in variables to avoid repetition
|
|
|
|
## Additional Resources
|
|
|
|
- Official n8n Expression docs: https://docs.n8n.io/code-examples/expressions/
|
|
- Luxon DateTime docs: https://moment.github.io/luxon/
|
|
- JavaScript reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript
|