写在前面:你的 n8n 流程为什么总是报错?
笔者在 N8N大学 社区里潜水时,发现很多新手都有一个共同的痛点:明明看着教程一步步做,结果到了“引用数据”这一步,直接卡死。看到 $json、$node、$input 这些带美元符号的变量,就像看天书。

“为什么我取不到上一个节点的数据?”“为什么我的 HTTP 请求返回值是空的?”这些报错,笔者当年也踩过坑。今天,咱们不讲虚的,就用大白话把 n8n 表达式里这“三驾马车”的区别给你彻底讲透。
一、核心概念:n8n 的数据流到底长啥样?
在深入变量之前,你必须先理解 n8n 的数据流转逻辑。n8n 不是像写代码那样一行行执行,而是像“水流”一样,通过 JSON 格式在节点之间传递。
每一个节点处理完数据,都会输出一个 JSON 对象。这个对象里包含了原始数据、处理结果、元数据等。而 $json、$node、$input,就是你在后续节点中“舀水”的三个不同勺子。
二、$json:最常用的“主菜”
$json 是 n8n 表达式里的绝对主角。简单来说,它代表了当前正在处理的这条数据。
当你使用 $json 时,你是在说:“我要访问当前数据载荷(Payload)里的内容。”
场景举例
假设你用 Webhook 节点接收了一个 POST 请求,Body 内容是:
{ "name": "n8n大学", "author": "笔者" }
在下一个节点(比如 Set 或者 HTTP Request)的参数里,如果你想引用这个名字,直接写:
{{ $json.name }}
结果就是:n8n大学。只要数据在当前的 JSON 结构里,$json 就是你的首选。
三、$node:跨节点的“上帝视角”
有时候,你需要的数据并不在当前的 JSON 结构里,而是散落在上游的某个特定节点中。这时候,$node 就派上用场了。
$node 允许你直接访问特定节点的输出数据,而不管中间经过了多少个节点。
语法结构
{{ $node.<节点名称>.json }}
场景举例
你的流程是:Webhook A -> HTTP Request B -> Set C。
在 Set C 节点里,你突然需要 Webhook A 里的某个数据(比如用户 ID),但这个数据在 HTTP Request B 里已经被覆盖或丢失了。
此时,你可以这样写:
{{ $node['Webhook A'].json.user_id }}
笔者提示:$node 很强大,但要慎用。过度依赖它会让你的流程逻辑变得错综复杂,像一团乱麻。尽量让数据通过 $json 顺流向后传递。
四、$input:处理多条数据的“搬运工”
这是最容易被混淆的一个。在旧版本的 n8n 中,你可能会经常看到 $input.item 或 $input.json。但在新版 n8n(0.171.0+)中,$input 的含义变得更加具体。
简单来说,$input 代表了当前节点的输入数据。它主要用于:
- 映射数据:将输入字段映射到输出字段。
- 处理二进制数据:在处理文件(如 PDF、图片)时,
$input.binary是唯一的选择。
场景举例
在 Read Binary File 节点中,你需要读取文件,文件名来自上一个节点。
表达式应写为:
{{ $input.json.file_path }}
或者在 Send Email 节点中,需要附加二进制附件:
{{ $input.binary.data }}
五、硬核对比:一张表看懂区别
为了方便大家复习,N8N大学 特意整理了一张对比表,建议收藏:
| 变量 | 核心含义 | 最佳使用场景 | 注意点 |
|---|---|---|---|
$json |
当前节点的 JSON 数据载荷 | 提取字段、做判断、拼接字符串 | 最常用,但在循环中可能指向当前循环项 |
$node |
指定节点的输出数据 | 跨层级取数、数据回填 | 慎用,容易导致流程维护困难 |
$input |
当前节点的输入接口 | 文件处理、字段映射 | 新版 n8n 中,二进制数据必须用它 |
六、避坑指南:90% 的错误都源于这两个原因
在 N8N大学 的社区辅导中,我们发现关于引用数据的报错通常集中在以下两点:
1. 节点没连对,数据源头就是空的
很多新手在调试时,忘记把上一个节点连接到当前节点。或者虽然连上了,但上一个节点是“死”的(没有执行过)。这时候你引用 $json 或 $node,结果自然是 undefined。
解决方案:点击“执行前一个节点”按钮,确保数据确实流过来了。在表达式编辑器里,n8n 会实时显示引用的数据预览,一定要看这个!
2. 数据层级搞错了
你以为数据是 { "name": "test" },实际上 n8n 给你的可能是 [{ "name": "test" }](一个数组)。这时候直接写 $json.name 拿不到值,得写 $json[0].name。
笔者经验:n8n 的数据流默认都是数组格式(即使是单条数据)。在表达式编辑器里点击数据预览,看清数据前面有没有中括号 [],这很重要。
FAQ 问答
Q1: 为什么我用 $node['节点名'].json 取不到值?
A:首先检查节点名称是否完全一致(包括大小写和空格)。其次,确保该节点在当前的运行记录中是绿色成功的状态。如果该节点在分支逻辑里没走到,数据自然也是空的。
Q2: $input.item 和 $input.json 还能用吗?
A:在最新的 n8n 版本中,$input.item 已被弃用或行为改变。推荐直接使用 $input.json 来获取输入的 JSON 数据,或者直接使用 $json(如果上下文正确)。对于二进制数据,请务必使用 $input.binary。
Q3: 我想在 HTTP Request 的 URL 里带参数,该怎么写?
A:这是最经典的 $json 用法。例如 URL 填写:https://api.example.com/users/{{ $json.user_id }}。只要当前数据里有 user_id 字段,就会自动替换。
总结与资源
搞定 n8n 的数据引用,本质上就是理清“当前数据” ($json)、“指定数据” ($node) 和“输入数据” ($input) 这三者的关系。笔者建议大家在实操时,多利用 n8n 强大的表达式实时预览功能,它是你最好的老师。
如果你还在为复杂的 n8n 配置头疼,欢迎访问 N8N大学 (n8ndx.com),这里有更多硬核的实战教程和避坑指南等着你。下次见!