复杂 JSON 清洗:使用 JavaScript Map/Reduce/Filter 在 n8n 中重构数据结构

2026-01-26 33 0

别再被“脏数据”折磨了,这可能是最硬核的一次数据清洗教学

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

复杂 JSON 清洗:使用 JavaScript Map/Reduce/Filter 在 n8n 中重构数据结构

兄弟,如果你也有这种痛苦,那你今天来对地方了。手动拼接节点就像用勺子挖隧道,效率低还容易出错。真正的高手,都懂得在 n8n 的 Code 节点里直接操刀 JavaScript。

今天,笔者就带你用最“大白话”的方式,把 JS 里的 Map、Filter、Reduce 这三把瑞士军刀在 n8n 中用出花来。看完这篇,你不仅能清洗数据,还能彻底搞懂数据流转的底层逻辑。

为什么你必须掌握 JS 节点?

很多新手习惯在 n8n 里堆砌 SetSpreadAggregate 节点。这在处理简单逻辑时没问题,但一旦遇到复杂的 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)。这里我们要用到 MapReduce

在代码框中输入以下逻辑:

// 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 自带节点能实现吗?

可以,但很痛苦。对于简单的字段重命名,用 SetSpread 没问题。但一旦涉及“根据条件修改字段”或“嵌套循环”,代码节点是唯一不把工作流搞成“意大利面条”的解法。建议边用边学,复制粘贴上面的模板改改就能用。

Q2: 代码节点里怎么调试报错?

n8n 的 Code 节点如果报错,通常会显示具体的 JS 错误信息。如果逻辑不通,最简单的调试方法是:在 return 之前,使用 console.log(你的变量),然后运行工作流,查看节点的 Details -> Output -> Console 栏目,能看到打印结果。

Q3: 处理大数组会不会卡死工作流?

单个节点处理几千条数据通常没问题。但如果数据量达到几万条,建议在 API 请求阶段就加上分页参数,或者在 Code 节点里分批处理。n8n 是内存执行,数据量过大会导致 Node.js 内存溢出。

总结与资源

数据清洗是自动化工作流的基石。掌握 Map、Filter、Reduce,意味着你从 n8n 的“使用者”进阶为了“掌控者”。不要畏惧代码,它们只是你处理数据的强力工具。

如果你在 n8n 中遇到了更棘手的 JSON 结构,欢迎在 N8N大学 的评论区留言,笔者会挑选典型案例在下期文章中拆解。

相关文章

安全加固:限制 n8n Code 节点访问文件系统与内网 IP (Sandbox 配置)
超越 SQLite:为什么生产环境必须连接 PostgreSQL 以及如何配置?
元数据获取:使用 $workflow.id 和 $execution.id 生成带追踪参数的回调链接
高并发架构:配置 Redis + n8n Worker 模式实现分布式任务处理
解决 OOM 崩溃:优化 n8n 大数据量处理时的内存占用 (Memory Leak) 技巧
多入口触发:如何让一个工作流同时支持 GET/POST 甚至多个不同路径的 Webhook?

发布评论