Skip to content
JSON Toolkit
Guides

n8n $json Expressions Cheat Sheet (With Examples)

October 29, 20266 min read

n8n expressions are small pieces of JavaScript inside double curly braces, and nearly all of them start with $json — the JSON of the item a node is working on. This cheat sheet collects the expressions you reach for most, each run against the same sample item so you can see exactly what comes back, plus the errors that trip people up and how to fix them.

Expressions need double braces and Expression mode

An n8n field only evaluates code when it is in Expression mode and the code sits inside double curly braces. {{ $json.searchterm }} returns the value of the searchterm field, while { $json.searchterm } with single braces is plain text and goes out exactly as typed. Text and expressions can share one field, so Order {{ $json.order_id }} is {{ $json.status }} becomes Order 1042 is paid.

$json is the JSON of the current item — shorthand for $input.item.json. Field names are case-sensitive: $json.searchTerm and $json.searchterm are different fields, and the wrong one quietly comes back empty.

The sample item used below

Every example in this cheat sheet runs against this item, so you can check each result yourself:

{
  "order_id": 1042,
  "status": "paid",
  "first name": "Ada",
  "customer": { "name": "Ada Lovelace", "email": "ada@example.com" },
  "items": [
    { "sku": "KB-01", "qty": 2, "price": 49 },
    { "sku": "MS-07", "qty": 1, "price": 25 }
  ],
  "folder": "exports/2026/october",
  "created_at": "2026-10-29T09:30:00Z"
}

Read fields, nested objects, and keys with spaces

Dots walk into nested objects, and brackets handle keys that dots can't. Long paths are easier to copy than to type: paste the item into the JSON tree viewer, hover a value, copy its path — such as $.customer.email — and swap the $ for $json inside the braces.

  • {{ $json.order_id }} returns 1042.
  • {{ $json.customer.email }} returns ada@example.com.
  • {{ $json['first name'] }} returns Ada — use brackets for keys with spaces, dashes, or dots.
  • {{ $json.shipping?.city ?? 'none' }} returns none instead of failing when a parent object is missing.
  • {{ $ifEmpty($json.status, 'unknown') }} returns paid, or unknown when the field is empty — n8n's built-in fallback.

Work with arrays

Arrays use zero-based indexes and the usual JavaScript methods, plus n8n helpers such as .last() and .sum():

  • {{ $json.items[0].sku }} returns KB-01, and {{ $json.items.last().sku }} returns MS-07.
  • {{ $json.items.length }} returns 2.
  • {{ $json.items.map(i => i.sku).join(', ') }} returns KB-01, MS-07.
  • {{ $json.items.map(i => i.qty * i.price).sum() }} returns 123.
  • {{ $json.items.filter(i => i.qty > 1).length }} returns 1.
  • To treat each element as its own item in later nodes, use the Split Out node rather than an expression.

Get data from other nodes

$json only sees the current node's input. To read an earlier node, call it by name with $('Node name') — the name must match exactly, spaces and capitals included:

  • {{ $('Webhook').item.json.body.email }} — the item that produced the current one.
  • {{ $('Fetch orders').first().json.order_id }} — always the first item, whichever one is being processed.
  • {{ $('Fetch orders').all().length }} — how many items that node returned.
  • {{ $('Fetch orders').all().map(i => i.json.order_id).join(', ') }} — one field from every item.
  • {{ $input.first().json.status }} — the first item coming into the current node.
  • If .item fails because n8n can't tell which item matches — common after a Code node that builds new items — use .first(), .last(), or .all() instead. Older workflows write $node['Name'].json; $('Name') is the current form.

Webhook data lives under body, query, and headers

A Webhook node outputs the whole request, so the field you want is one level down. Forgetting body is the most common reason a webhook expression comes back empty:

  • {{ $json.body.email }} — a field from a JSON or form body.
  • {{ $json.query.page }} — the page value from a URL ending in ?page=2.
  • {{ $json.params.id }} — a path parameter, for a webhook path like order/:id.
  • {{ $json.headers['user-agent'] }} — header names arrive in lowercase and contain dashes, so use brackets.

Replace text and use regex

Expressions are JavaScript, so string methods behave as they do in code. One catch: .replace() with a plain string changes only the first match — use a regular expression with the g flag, or .replaceAll(), to change every one.

  • {{ $json.status.toUpperCase() }} returns PAID, and {{ $json.status.toTitleCase() }} returns Paid.
  • {{ $json.items[0].sku.replace(/-\d+$/, '') }} returns KB — a regex that strips a trailing number.
  • {{ $json.folder.replace(/\//g, '\\') }} returns exports\2026\october. Inside a regex the slash is written \/, and a single backslash in a string is written '\\'.
  • {{ $json.folder.replaceAll('/', '-') }} returns exports-2026-october.
  • {{ $json.customer.email.split('@')[1] }} returns example.com.

Dates with $now, $today, and Luxon

$now and $today are Luxon DateTime objects in the workflow's time zone, and an ISO date string becomes one with .toDateTime():

  • {{ $now.toFormat('yyyy-MM-dd') }} — today's date, such as 2026-10-29.
  • {{ $today.minus(1, 'days').toFormat('yyyy-MM-dd') }} — yesterday.
  • {{ $json.created_at.toDateTime().toFormat('d LLL yyyy') }} returns 29 Oct 2026.
  • {{ $now.plus(7, 'days').toISO() }} — a full timestamp one week from now.

Pass JSON on as JSON

When a field needs the JSON itself — an HTTP Request body, a Slack message, a database column — turn the object into a string first, and turn stringified JSON back into an object before reading from it:

  • {{ $json.customer.toJsonString() }} returns {"name":"Ada Lovelace","email":"ada@example.com"}, and {{ JSON.stringify($json.customer) }} does the same.
  • {{ $json.payload.parseJson().id }} returns 7 when payload is a string such as {\"id\": 7}.
  • Got a field escaped like that and want to read it first? The JSON stringify tool unescapes it back into readable JSON.

If/else and multi-line logic

A ternary or n8n's $if() covers a quick either/or. For anything with several steps, wrap plain JavaScript in an immediately invoked function, the pattern the n8n docs recommend:

{{ (() => {
  const total = $json.items.reduce((t, i) => t + i.qty * i.price, 0);
  return total > 100 ? 'free shipping' : 'standard';
})() }}
  • {{ $json.items.length > 1 ? 'multi' : 'single' }} returns multi.
  • {{ $if($json.status === 'paid', 'ship', 'hold') }} returns ship.
  • The function above returns free shipping, because the order totals 123.
  • Past a few lines, move the logic into an Edit Fields (Set) node or a Code node. In a Code node set to Run Once for All Items there is no single current item, so loop over $input.all() and read item.json.
  • Reshaping a whole object into a new structure? The JSON Mapper builds the mapping visually and generates JavaScript you can adapt for a Code node.

Expression errors and how to fix them

Most broken expressions fail in one of a few ways:

  • “Can't get data for expression” — the expression reads a node that has not run yet. Run the workflow up to that node, or check $('Node name').isExecuted first.
  • “Referenced node is unexecuted” — the named node is not on the branch that ran. Rewire the workflow so it executes first, or read the value from a node that did run.
  • “Invalid syntax” — usually a stray character, such as the trailing dot in {{ $('If').item.json. }}.
  • An empty result with no error — the path is wrong. Check spelling and capitals, whether webhook data sits under body, and whether the value is inside an array that needs an index.
  • {{ $env.MY_VAR }} is refused — since n8n 2.0, N8N_BLOCK_ENV_ACCESS_IN_NODE defaults to true, so a self-hosted instance blocks environment variables in nodes unless you change that setting.

Run n8n on your own server

Every expression here works the same on n8n Cloud and on a self-hosted instance. If you would rather keep your workflows, and the data they touch, on a machine you control, the self-hosting section of our deploy guide walks through running n8n in Docker on a VPS, with a persistent volume so nothing is lost on restart.

Try it yourself

Turn JSON into an interactive, searchable tree you can expand and collapse.

Open JSON Tree Viewer