The Transform node is a deterministic, AI-free utility for shaping data as it flows between steps. It has two modes — Structured for field-by-field output, and Plaintext for free-form templates — and an optional Iterate over field that runs the transform once per element of an input array. Use it when the shape you need is known and predictable. For shaping that requires LLM judgment (summarising, classifying, inferring missing fields), reach for an AI Connector node instead.Documentation Index
Fetch the complete documentation index at: https://docs.spojit.com/llms.txt
Use this file to discover all available pages before exploring further.
When to use
- Rename or remap fields between connectors (e.g.
firstName→first_name). - Extract a subset of fields from a larger object.
- Build a JSON payload for a downstream HTTP/connector call.
- Transform every element of an array in one step (map mode).
- Combine values from multiple upstream nodes into a single object.
Templates
Field values are written using{{ var.path }} template syntax — the same syntax used everywhere else in the workflow editor. See Passing Data Between Nodes for the full reference.
| Template | What it references |
|---|---|
{{ input.field }} | A field from the trigger payload. |
{{ stepOutput.field }} | A field from an upstream step’s output (whatever you set as its Output Variable). |
{{ item.field }} and {{ index }} | Only available when Iterate over is set — the current element and its zero-based index. |
"Hi {{ name }}" are stringified.
Structured mode
Define your output shape field by field. Each leaf field carries a template that resolves at execution time.- Click Add Field to add an output property.
- Pick a name and type (
string,number,boolean,array,object). - For leaves, fill in the template with
{{ … }}references. - For
object, add nested children. Forarray, choose the item type — and for arrays of objects, define the per-item children. - Toggle JSON (top right) to edit the schema as raw JSON when you’d rather paste a structure than click through it.
order:
id(string) →{{ order.id }}customer_email(string) →{{ order.customer.email }}amount(number) →{{ order.totalPrice }}
amount stays a number because the template is the entire field value.
Field types and value coercion
The declared field type controls how literal values you type are persisted:- String — the value is sent as-is.
- Number — a literal like
42is sent as the number42. Non-numeric literals fall back to a string. - Boolean —
trueandfalse(case-insensitive) become the actual booleanstrue/false. Anything else falls back to a string. - Object / Array — shape is built from the children you define.
{{ … }}), the field type does not coerce — the engine returns whatever type the resolved expression produced. So a String field with template {{ item }} (where item is a user object) outputs the object, not a stringified one. Match the declared field type to what your template actually resolves to.
Plaintext mode
Paste any text or JSON template and substitute{{ … }} references inline. Use this when you’d rather write the payload as a literal block — useful for HTTP request bodies, Slack message text, or any sufficiently large object.
The Output as JSON toggle controls how the rendered output is treated:
- Off — the result is the rendered string verbatim.
- On — the rendered string is parsed as JSON; the parsed object/array is what downstream nodes receive. If the rendered output isn’t valid JSON, the workflow fails with a clear error so the bug is caught at the transform, not three steps downstream.
order input as above, resolves to:
Iterate over (map mode)
Set Iterate over to a template expression that resolves to an array — the transform then runs once per element. Inside templates,{{ item }} is the current element and {{ index }} is its zero-based position. The transform’s Output Variable receives the array of all per-iteration results.
Example. With users set to:
{{ users }} and a structured field mapped (Object type) with the children name → {{ item.first_name }} and email → {{ item.email }}. The output variable holds:
Drill into the upstream object to find the array
A common surprise: most upstream steps don’t return a bare array — they return an object that wraps the array. Common shapes:- AI Connector (agent mode) with a Response Schema → the step’s value is the schema object, e.g.
{ "users": [ … ] }→ use{{ result_step1.users }}. - HTTP / direct connector → typically
{ "data": [ … ], "status": 200, "headers": { … } }(e.g. JSONPlaceholder) → use{{ result_step1.data }}.
forEach 'items' template "{{ result_step1 }}" must resolve to an array, got object (resolved object has keys: data, status, headers) — so you can spot the missing path segment immediately.
Output
The resolved value is bound to the Output Variable name (defaulting toresult_<nodeId> when blank). Reference it from downstream nodes the same as any other step result — e.g. {{ shapedUser.email }}. For map mode, this name holds the full collected array.
Tips
- Chain multiple transforms when reshaping in stages — it’s cheaper to read than one giant template.
- For advanced operations like JSONPath queries, deep flattening, or merging nested objects, see the JSON Tools connector.
- A template that points at nothing (e.g. a typoed variable name) resolves to
null. Use the structured editor’s JSON view when debugging — it shows exactly the templates being sent to the engine.