跳转到内容

新手 5 大表达式坑 · 提前免疫

第 3 章 · 第 5 节

n8n 论坛上 80% 的表达式问题,归根结底是同 5 个坑反复出现。本节直接亮答案——看完这 5 个,你就比 90% 的新手少踩坑

坑 1 · 忘记切表达式模式(最高频)

Section titled “坑 1 · 忘记切表达式模式(最高频)”
trap-1.txt
场景:HTTP Request 节点,URL 想动态用 $json.id 输入: https://api.com/users/{{ $json.id }} 期望: https://api.com/users/123 实际: https://api.com/users/{{ $json.id }} ← 字面量! 返回: 404 Not Found 原因: 输入框处于固定值模式,没点 fx 切换。 解药: 1. 鼠标悬停 URL 输入框 → 点右上角 fx 按钮 2. 输入框背景变粉、左上角出现 "Expression" 字样 → 现在是表达式模式 3. 重新填 {{ $json.id }} → 会被求值 诊断口诀: "表达式没生效?先看背景色"

坑 2 · .item 引用错(出现 Merge / SplitInBatches 时)

Section titled “坑 2 · .item 引用错(出现 Merge / SplitInBatches 时)”
trap-2.txt
场景: [Get Users (5 items)] → [SplitInBatches (size=2)] → [Send Email] Send Email 节点 To 字段: ={{ $('Get Users').item.json.email }} 报错: "Couldn't find which item to use for this expression" 原因: SplitInBatches 重组了数据流,n8n 无法确定 "Send Email 的当前迭代" 和 "Get Users 的某个 item" 之间的配对关系。 解药 A(推荐):用 .first() ={{ $('Get Users').first().json.email }} ← 永远拿第一项,不出错 解药 B:用 $json(紧邻上游已是 SplitInBatches 输出) ={{ $json.email }} 解药 C:用 .itemMatching($itemIndex) 按下标 ={{ $('Get Users').itemMatching($itemIndex).json.email }} 诊断口诀: ".item 是智能的,但智能并不总对"
trap-3.txt
场景:Google Sheets 节点读出来 price 字段,下游想求总额 输入数据(实际!): [ { product: "A", price: "9.99" }, ← 注意是字符串 { product: "B", price: "19.99" } ] 错误尝试: ={{ $json.price + 0.01 }} → "9.990.01" ❌ 正确: ={{ Number($json.price) + 0.01 }} → 10 ✅ ={{ parseFloat($json.price) + 0.01 }} → 10 ✅ ={{ +$json.price + 0.01 }} → 10 ✅ (前缀 + 简写) 来源类型常识: Sheets 单元格 → string Webhook query 参数 → string Webhook JSON body → 保留 JSON 类型(number 还是 number) Postgres / MySQL → 保留类型 HTTP API response → 看响应 JSON 诊断口诀: "+ 出来是字符串拼接?前面没 Number()"

坑 4 · 嵌套字段不存在导致整个表达式爆

Section titled “坑 4 · 嵌套字段不存在导致整个表达式爆”
trap-4.txt
场景:HTTP Request 返回 user 字段有时存在有时不存在 错误: ={{ $json.user.profile.email.toLowerCase() }} → 当 user 为 null 时: TypeError: Cannot read properties of null (reading 'profile') → 整个 workflow 在这个节点挂掉 正确(用可选链 ?. + 默认值 ??): ={{ $json.user?.profile?.email?.toLowerCase() ?? '(无邮箱)' }} 完整心法: - 不确定上游有没有的字段 → ?. - 想给空值一个默认 → ?? "默认" - 想给 null/0/"" 等所有"假值"默认 → || "默认" ?? 比 || 严格:?? 只在 null/undefined 时兜底;|| 在所有假值时兜底。 诊断口诀: "TypeError: Cannot read properties of undefined" = 该用 ?. 了

坑 5 · Schedule 触发器时区跟 cron 表达式时区不一致

Section titled “坑 5 · Schedule 触发器时区跟 cron 表达式时区不一致”
trap-5.txt
场景:你在 Cloud 部署,想让 workflow "每天北京时间 9:00 跑" 错误尝试: Schedule 节点 → Cron Expression: 0 9 * * * 期望:每天 09:00 跑 实际:每天 17:00 跑(北京时间) 原因: Cloud 默认 UTC,cron "0 9 * * *" = UTC 9:00 = 北京 17:00 解药 A:改 cron 用 UTC 时间 0 1 * * * ← UTC 1:00 = 北京 9:00 解药 B(自托管):改环境变量 GENERIC_TIMEZONE=Asia/Shanghai 然后 0 9 * * * 就是北京 9:00 了 解药 C:用 Interval 模式 + 自己加判断 Schedule (每小时) → IF (now.hour === 9 in shanghai TZ?) → 继续 诊断方法: - 在节点里加一个 Set,值 = {{ $now.toISO() }} + {{ $now.zoneName }} - 跑一次看真实时区是不是预期 诊断口诀: "时间不对?先打印 $now.zoneName"

坑 6 · $json 在 Code 节点里不能直接用

Section titled “坑 6 · $json 在 Code 节点里不能直接用”

Code 节点用 items[0].json.x 取数据,不能$json$json 只在表达式里有效。

$json["客户姓名"] ✅
$json.客户姓名 ✅(也可但有特殊字符就不行
$json["customer name"] ✅

{{ }} 里只允许写表达式,不能写语句。要循环或条件分支:

  • 简单:用三元 ?:
  • 复杂:换 Code 节点

本节要点回顾(也是整个第 3 部分回顾)

Section titled “本节要点回顾(也是整个第 3 部分回顾)”
解药
表达式没生效fx 切表达式模式
.item 报 Couldn’t find改用 .first().itemMatching($itemIndex)
数字字段变字符串Number(x)+x 显式转
嵌套字段 undefined 报错?. 安全链 + ?? 默认值
Schedule 时区不对GENERIC_TIMEZONE 或 cron 用 UTC

至此你已学完 第 3 部分。下一部分是真正进入”工业级 workflow” 的流程控制 (Flow Logic)