别再被“脏数据”折磨了,这可能是最硬核的一次数据清洗教学
笔者在 N8N大学 的后台经常收到这样的求助:“API 拉回来的 JSON 数据结构太乱了,嵌套套嵌套,我想把它们拍平,或者只取其中几个字段,用 n8n 自带的节点是不是得连拖十几个?”

兄弟,如果你也有这种痛苦,那你今天来对地方了。手动拼接节点就像用勺子挖隧道,效率低还容易出错。真正的高手,都懂得在 n8n 的 Code 节点里直接操刀 JavaScript。
今天,笔者就带你用最“大白话”的方式,把 JS 里的 Map、Filter、Reduce 这三把瑞士军刀在 n8n 中用出花来。看完这篇,你不仅能清洗数据,还能彻底搞懂数据流转的底层逻辑。
为什么你必须掌握 JS 节点?
很多新手习惯在 n8n 里堆砌 Set、Spread 和 Aggregate 节点。这在处理简单逻辑时没问题,但一旦遇到复杂的 JSON 嵌套,工作流就会变得又长又臃肿,维护起来简直是噩梦。
使用 Code 节点(底层是 Node.js)配合 JS 数组方法,优势非常明显:
- 性能炸裂:一次遍历完成所有操作,而不是分五六步慢慢倒腾。
- 逻辑清晰:代码即文档,复杂的逻辑写成函数一目了然。
- 灵活性高:不管 API 返回的 JSON 是什么“妖孽”结构,你都能把它驯服成想要的样子。
实战演练:三步搞定复杂 JSON 重构
假设我们从某个 CRM 系统拉到了一份订单数据,结构如下(这就是典型的“脏数据”):
{
"results": [
{
"id": 101,
"user": { "name": "张三", "level": "VIP" },
"items": [{ "sku": "A001", "price": 100 }, { "sku": "B002", "price": 200 }]
},
{
"id": 102,
"user": { "name": "李四", "level": "普通" },
"items": [{ "sku": "C003", "price": 50 }]
}
]
}
需求:我要提取出所有订单,只保留用户姓名、订单总金额,并且过滤掉总金额小于 100 的订单。
第一步:在 n8n 中准备 Input 数据
在你的工作流中,先添加一个 Set 节点(或者 Manual 触发器),把上面那段 JSON 数据填入,作为我们的模拟源数据。记得把 Output 设置为 JSON。
第二步:插入 Code 节点(核心操作)
在 Set 节点后面添加一个 Code 节点(JavaScript)。这里我们要用到 Map 和 Reduce。
在代码框中输入以下逻辑:
// 1. 获取上一步传来的 items
const items = $input.all();
// 2. 使用 Map 重构结构 + Reduce 计算总价
const processedOrders = items.map(item => {
const rawData = item.json.results;
// 遍历原始结果,进行数据转换
return rawData.map(order => {
// 使用 Reduce 计算该订单总价
const totalPrice = order.items.reduce((sum, product) => sum + product.price, 0);
return {
userName: order.user.name, // 提取扁平字段
total: totalPrice, // 计算得出的新字段
isVip: order.user.level === 'VIP'
};
});
}).flat(); // 这里的 flat 是为了处理多层数组结构,视具体情况而定
// 3. 使用 Filter 进行过滤
const finalResult = processedOrders.filter(order => order.total >= 100);
// 4. 返回结果给 n8n
return { json: finalResult };
笔者提示:在 n8n 的 Code 节点中,$input.all() 用于获取上游所有数据项。如果你的数据源只有一项,也可以直接用 $input.first().json。
第三步:输出与验证
在 Code 节点后接一个 HTTP Response 或者 Debug 节点。你会发现,原本层层嵌套的 JSON,现在变成了清爽的数组:
[
{ "userName": "张三", "total": 300, "isVip": true }
]
李四因为总价只有 50,已经被 Filter 无情地过滤掉了。
避坑指南:新手最容易犯的两个错
1. 忘记处理数据层级
很多 API 返回的数据包裹在 { "data": [...] } 或者 { "results": [...] } 中。直接对 $input 使用数组方法会报错。一定要先定位到具体的数组层级,比如 data.json.results.forEach(...)。
2. 混淆 Map 和 ForEach
记住,Map 是有返回值的,它会生成一个新数组;forEach 只是单纯的遍历,返回 undefined。如果你在 n8n 里想生成新的数据结构传给下一个节点,必须用 map。
高级技巧:使用 Reduce 做数据聚合
Reduce 初看很晦涩,但它其实是万能的。笔者举个例子:你想统计所有订单中,哪个 SKU 出现的次数最多?
用 Reduce 几行代码就能搞定:
const allItems = $input.first().json.results.flatMap(o => o.items);
const itemCounts = allItems.reduce((acc, curr) => {
acc[curr.sku] = (acc[curr.sku] || 0) + 1;
return acc;
}, {});
这就是 Reduce 的魅力:它能把一个数组“折叠”成任意形态——对象、数字、字符串都可以。
FAQ:关于 n8n 代码节点的常见问题
Q1: 我不懂 JS,只用 n8n 自带节点能实现吗?
可以,但很痛苦。对于简单的字段重命名,用 Set 或 Spread 没问题。但一旦涉及“根据条件修改字段”或“嵌套循环”,代码节点是唯一不把工作流搞成“意大利面条”的解法。建议边用边学,复制粘贴上面的模板改改就能用。
Q2: 代码节点里怎么调试报错?
n8n 的 Code 节点如果报错,通常会显示具体的 JS 错误信息。如果逻辑不通,最简单的调试方法是:在 return 之前,使用 console.log(你的变量),然后运行工作流,查看节点的 Details -> Output -> Console 栏目,能看到打印结果。
Q3: 处理大数组会不会卡死工作流?
单个节点处理几千条数据通常没问题。但如果数据量达到几万条,建议在 API 请求阶段就加上分页参数,或者在 Code 节点里分批处理。n8n 是内存执行,数据量过大会导致 Node.js 内存溢出。
总结与资源
数据清洗是自动化工作流的基石。掌握 Map、Filter、Reduce,意味着你从 n8n 的“使用者”进阶为了“掌控者”。不要畏惧代码,它们只是你处理数据的强力工具。
如果你在 n8n 中遇到了更棘手的 JSON 结构,欢迎在 N8N大学 的评论区留言,笔者会挑选典型案例在下期文章中拆解。