Messy JSON in n8n: normalize once, then keep the workflow clean
APIs and webhooks often return one item containing a nested array. That is fine for transport, but it becomes awkward when the next nodes expect one n8n item per lead, order, record or article.
Why this breaks downstream nodes
A payload such as the example below is still a single n8n item. The leads array exists inside that item rather than as separate workflow items.
{
"source": "webhook",
"account": "ACME",
"leads": [
{"id":"L-001","name":"Alex"},
{"id":"L-002","name":"Sam"}
]
}
If later mapping, looping or batch logic expects one item per lead, passing the object through unchanged can produce confusing expressions, repeated handling or a loop that behaves differently from what you intended.
The robust normalization pattern
1. Find the array that actually represents your records
Common paths include payload.contacts, payload.data.items, payload.results or a similarly nested field. Do not assume the visible top-level object is the row set.
2. Validate before transforming
const payload = $input.first().json;
const rows = payload.data?.items;
if (!Array.isArray(rows)) {
throw new Error('Expected an array at data.items');
}
A clear failure near the top of the workflow is easier to diagnose than a chain of downstream nodes receiving the wrong shape.
3. Emit one n8n item per record
return rows.map((row, index) => ({
json: {
...row,
source: payload.source ?? null,
account: payload.account ?? null,
array_index: index
}
}));
This gives later nodes a predictable stream: one item per record, plus the parent fields you intentionally preserved.
4. Normalize once
Keep raw API/webhook shape handling close to the start of the workflow. Downstream nodes should work with a stable internal schema instead of repeatedly checking whether fields moved or became nested.
5. Test with sample data first
Use representative test payloads before connecting production credentials. Store credentials in n8n credentials rather than in Code nodes or shared workflow JSON.
When the payload shape changes
Optional chaining such as payload.data?.items can prevent an immediate property-access crash, but it does not prove the expected array is present. Pair defensive reads with explicit validation and a deliberate fallback or error path.
Try it without uploading your data
The free PAUL n8n Payload Inspector runs in your browser. Paste JSON locally, find nested array paths, preview clean n8n-style items and generate a starter Code node.
What the Rescue Kit adds
The paid Rescue Kit is a tested starter workflow rather than a promise that every third-party schema will work unchanged. It includes a working nested-array flattening pattern, quick-start notes, troubleshooting guidance and a QA/proof step. It was built and executed successfully on n8n 2.40.5 in September 2026.