core.set

Set (core.set)

Build or patch each item's JSON: add fields, overwrite fields, or reshape the item to exactly the fields you name. One output item per input item, in order.

Parameters

ParameterTypeDefaultDescription
modemerge | keep_onlymergemerge patches your fields into the item's existing JSON. keep_only replaces the item's JSON with exactly your fields.
fieldslist of {name, value}[]The fields to write. Both name and value accept {{ }} expressions, evaluated per item.

Behavior

merge (default) — keeps everything already on the item and writes your fields over it:

input   {"a": 1, "b": "original"}
fields  b = "patched", c = "new"
output  {"a": 1, "b": "patched", "c": "new"}

keep_only — the output item contains only your fields (use it to trim noisy API responses down to what downstream nodes need):

input   {"a": 1, "noise": true, "more": [1, 2]}
fields  kept = {{ $json.a }}
output  {"kept": 1}

Expressions keep their type. A value that is a single whole expression returns the native value — numbers stay numbers, objects stay objects:

value "{{ $json.count }}"        → 7          (number)
value "{{ $json.address }}"      → {…}        (object)
value "total: {{ $json.count }}" → "total: 7" (mixed text interpolates as a string)

Non-string literal values (real numbers, booleans, objects, null) pass through untouched.

Per-item evaluation. Expressions run once per input item, so {{ $json.n * 2 }} doubles each item's own n.

Dynamic field names. name accepts expressions too: name = {{ $json.column }} writes under whatever key that item carries.

Binary passes through in both modes — attachments on the input item stay on the output item, untouched.

Quirks & tips

  • No dot-path nesting (differs from n8n). name = "a.b" writes the literal key "a.b" — it does not create {"a": {"b": …}}. To build nested structure, set the whole object: value = {{ {"b": $json.x} }} under name = "a".
  • A missing reference stops the node. {{ $json.nope }} on an item without nope fails the run with an error naming this node — it does not silently write null. Guard with the IF/Filter nodes upstream if a field is genuinely optional.
  • Duplicate names: last one wins. Two rows named x → the lower row's value is what lands.
  • Setting a value to null keeps the key ({"a": null}), it does not delete it. To drop keys, switch to keep_only and name what survives.
  • A row saved without a value writes null — harmless mid-edit, worth knowing when you see nulls appear.
  • Unicode and empty-string names are accepted as literal keys.

Related

  • Filter / IF — route or drop items instead of reshaping them.
  • Split Out — explode a list field into one item per element.
  • Code — arbitrary reshaping in Python when field mapping isn't enough.