Skip to content
Expedify
Logic & Data

Module · Data

Transform Data

Lesson 10 of 11 · 7 min

Data arriving from outside is rarely shaped the way your CRM wants it. A partner posts a payload with the useful part encoded as a string. An AI returns perfect JSON with “Sure, here you go:” in front of it. A spreadsheet row arrives with everything as text.

Transform Data is the node that fixes the shape. Its most common job is turning something that contains JSON into something you can read fields out of.

Three modes

`transform_type` decides which of the other fields matter.

transform_type

What it holds
Type of transformation (auto, json_parse, custom_code) One of: auto · json_parse · custom_code Defaults to auto.

input_source

What it holds
Input source path

parse_strategies

What it holds
Parse strategies to try for JSON extraction

code

What it holds
Custom transformation code

timeout

What it holds
Code execution timeout Defaults to 5.

imports

What it holds
Allowed imports for code execution

json_parse

Does
Extracts JSON out of whatever it is given.
Use when
The common case, and the one worth learning properly.

auto

Does
Inspects the input and decides.
Use when
Quick and fine — but be explicit once you know what arrives.

custom_code

Does
Runs a small snippet with a restricted import list.
Use when
Reshaping that parsing alone cannot do.

Why parsing needs three strategies

The interesting field is parse_strategies, and its default — ["direct", "markdown", "regex"] — is a description of how messy real inputs are. They are tried in order:

  1. direct — the value already is JSON. Parse it and stop.
  2. markdown — the JSON is inside a fenced code block, which is how language models return it when asked for JSON.
  3. regex — last resort: find something JSON-shaped inside surrounding prose.
what an LLM actually returns
Sure! Here's the classification you asked for:

```json
{"segment": "enterprise", "confidence": 0.82}
```

Let me know if you'd like it broken down further.
direct fails, markdown succeeds — which is why the ladder exists rather than a single parse.

This is the whole reason to reach for the node instead of writing your own parse. Handling that ladder by hand is twenty lines of string-wrangling that breaks the first time a model phrases its preamble differently.

A worked example

A JSON string becomes fields

The webhook's payload carries JSON inside a string; the transform makes it readable.

Scroll for all 3 steps →

The result comes back at {{transformdata_1.output}}, so a parsed field is {{transformdata_1.output.segment}}. The node also reports which transform_type ran and what it was given — useful when the answer is not what you expected.

Watch out: For JSON from an LLM: transform_type: json_parse + input_source; read the result as {{alias.output.<field>}}.

Parsing an AI reply

Same node, same settings, with input_source pointed at the AI node's output. One thing to get right, because it is the most common broken reference in this pairing: the LLM Integration node exposes output and parsed — there is no response field, though everyone tries it first.

Check whether you need this at all. An AI node that already returns structured output gives you {{alias.parsed.<key>}} directly. Transform Data is for when the reply is prose that happens to contain JSON — which is what you get from a plain prompt asking for JSON.

Transform Data or Custom Function?

They overlap, and the distinction is worth holding:

Get JSON out of a messy string

Reach for
transform_data — the strategy ladder is the whole value

Pull a nested field into a flat one

Reach for
transform_data in custom_code mode

Business logic — scoring, banding, branching rules

Reach for
custom_function — and give it a name

Anything you would struggle to explain in one sentence

Reach for
custom_function

Transform Data's custom_code mode runs with a restricted import list (json, re, datetime, math) and a 5-second default timeout. That is deliberate: it is for reshaping, and the tight budget is a hint that logic belongs in the other node.

Try it

  1. Point a Transform Data at any field that holds a JSON string, with transform_type on json_parse.
  2. Read one parsed field downstream as {{transformdata_1.output.<field>}}.
  3. Now wrap that same JSON in a sentence of prose and run it again — it still works, and the log will tell you which strategy got there.
  4. Finally, feed it something that is not JSON at all, and see what the node reports rather than guessing.

Next: Database Query — when the data you need is not in the payload at all.