在 n8n 中构建自动化工作流时,表达式(Expressions) 是连接各个节点、处理和转换数据的核心技能。许多初学者虽然已掌握 JSON 基础,但却不知道如何在节点之间传递和处理数据,导致工作流总是显得「死板」和「固定」。
本教程将带你深入 n8n 的灵魂——表达式系统,通过通俗易懂的讲解和实战案例,让你彻底告别静态工作流,解锁数据自动化的真正潜力。
表达式 是包含在 {{ }} 双花括号中的 JavaScript 代码片段。它们让你能够:
基础语法:
{{ 你的 JavaScript 代码 }}示例: 访问来自上一个节点的城市信息
{{ $json.city }}在 n8n 中,使用 $json 变量访问当前项目的 JSON 数据:
| 表达式 | 说明 | 用途 |
|---|---|---|
{{ $json }} | 获取整个 JSON 对象 | 查看完整数据结构 |
{{ $json.fieldName }} | 获取特定字段 | 提取单个数据值 |
{{ $json.address.city }} | 访问嵌套属性 | 获取深层数据 |
{{ $itemIndex }} | 获取当前项目索引(从 0 开始) | 循环处理中定位位置 |
实际例子:
假设前一个节点返回了用户信息:
{
"name": "张三",
"email": "zhangsan@example.com",
"address": {
"city": "北京",
"zipcode": "100000"
}
}你可以这样访问:
{{ $json.name }} // 返回: "张三"
{{ $json.address.city }} // 返回: "北京"
{{ $json.email }} // 返回: "zhangsan@example.com"在实际工作中,数据并不总是完整的。你需要检查数据是否存在,以及是否符合预期。
三元运算符是一种简洁的条件判断方式:
{{ 条件 ? 为真时返回值 : 为假时返回值 }}示例:检查变量是否为空
{{ $json.phone !== undefined ? $json.phone : "未提供" }}这个表达式的含义:
$json.phone 存在(不是 undefined),返回该值??){{ $json.phone ?? "未提供" }}这个运算符只在值为 null 或 undefined 时才使用默认值,对 0、false 或空字符串保持原值。
||){{ $json.phone || "未提供" }}注意:这个运算符会将 0、false、空字符串等「假值」都替换为默认值。
对比三种方法:
| 方法 | 当值为 null/undefined | 当值为 0/false/空字符串 |
|---|---|---|
| 三元运算符 | 返回默认值 | 返回原值 |
?? 空值合并 | 返回默认值 | 返回原值 ✓ |
|| 逻辑OR | 返回默认值 | 返回默认值 |
原因: 前置节点尚未执行,或者你引用的节点不存在。
解决方案:
{{ $input.first() !== undefined ? $json.fieldName : "节点未执行" }}原因: 输出了格式不规范的 JSON,或引用了不存在的字段。
解决方案:
// ❌ 错误:引用不存在的字段
{{ $json.username.profile.notExistField }}
// ✓ 正确:先检查字段是否存在
{{ $json.username?.profile?.notExistField ?? "字段不存在" }}原因: 表达式代码有 JavaScript 语法错误。
解决方案:
当前置节点返回多个项目时,使用以下方法:
| 方法 | 说明 |
|---|---|
{{ $input.first() }} | 获取第一项数据 |
{{ $input.last() }} | 获取最后一项数据 |
{{ $input.all() }} | 获取所有项目(返回数组) |
示例:获取所有用户名称
{{ $input.all().map(item => item.json.name).join(", ") }}{{ $json.name.toUpperCase() }} // 转换为大写
{{ $json.email.toLowerCase() }} // 转换为小写
{{ $json.text.includes("关键词") }} // 检查是否包含子串
{{ $json.name.substring(0, 3) }} // 提取前 3 个字符{{ typeof $json.age === 'number' ? $json.age : 0 }} // 类型检查
{{ $json.enabled === true ? "启用" : "禁用" }} // 布尔值判断
{{ Array.isArray($json.items) ? $json.items.length : 0 }} // 数组长度检查{{ $now.toFormat("yyyy-MM-dd") }} // 当前日期,格式化为 YYYY-MM-DD
{{ $today }} // 今天午夜时间
{{ $now.plus({days: 7}) }} // 当前时间加 7 天现在我们构建一个真实场景的工作流:从 API 接收用户注册数据,验证数据完整性,然后根据验证结果执行不同的操作。
将以下 JSON 代码复制到 n8n 中,选择 File > Import from URL 或 File > Import from Clipboard:
{
"name": "数据验证与条件处理工作流",
"description": "接收用户数据,验证完整性,根据结果执行不同操作",
"nodes": [
{
"parameters": {},
"id": "webhook-start",
"name": "webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [250, 300],
"webhookId": "webhook-example"
},
{
"parameters": {
"jsCode": "// 验证用户数据的完整性\nconst data = $json;\nconst errors = [];\n\n// 检查必填字段\nif (!data.name || data.name.trim() === '') {\n errors.push('姓名不能为空');\n}\n\nif (!data.email || !data.email.includes('@')) {\n errors.push('请输入有效的电子邮件地址');\n}\n\nif (!data.phone) {\n errors.push('电话号码不能为空');\n}\n\n// 检查年龄是否有效\nif (data.age && (data.age < 18 || data.age > 100)) {\n errors.push('年龄必须在 18-100 之间');\n}\n\nreturn {\n isValid: errors.length === 0,\n errors: errors,\n data: {\n name: data.name?.trim() || '未提供',\n email: data.email?.toLowerCase() || '未提供',\n phone: data.phone || '未提供',\n age: data.age ?? 0,\n registrationTime: new Date().toISOString()\n }\n};"
},
"id": "function-validate",
"name": "数据验证",
"type": "n8n-nodes-base.functionItem",
"typeVersion": 1,
"position": [450, 300]
},
{
"parameters": {
"conditions": {
"boolean": [
{
"value1": "{{ $json.isValid }}",
"value2": true,
"operation": "equals"
}
]
}
},
"id": "if-validation",
"name": "验证是否通过",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [650, 300]
},
{
"parameters": {
"content": "✅ 用户注册成功!\n\n姓名:{{ $json.data.name }}\n邮箱:{{ $json.data.email }}\n电话:{{ $json.data.phone }}\n年龄:{{ $json.data.age }}\n注册时间:{{ $json.data.registrationTime }}"
},
"id": "webhook-response-success",
"name": "成功响应",
"type": "n8n-nodes-base.webhookRespond",
"typeVersion": 1,
"position": [850, 150]
},
{
"parameters": {
"content": "❌ 用户注册失败!\n\n错误信息:\n{{ $json.errors.join('\\n') }}\n\n请检查以下信息并重试:\n- 姓名(必填)\n- 有效的电子邮件地址(必填)\n- 电话号码(必填)\n- 年龄 18-100 之间(可选)"
},
"id": "webhook-response-error",
"name": "错误响应",
"type": "n8n-nodes-base.webhookRespond",
"typeVersion": 1,
"position": [850, 450]
}
],
"connections": {
"webhook-start": {
"main": [
[
{
"node": "function-validate",
"type": "main",
"index": 0
}
]
]
},
"function-validate": {
"main": [
[
{
"node": "if-validation",
"type": "main",
"index": 0
}
]
]
},
"if-validation": {
"main": [
[
{
"node": "webhook-response-success",
"type": "main",
"index": 0
}
],
[
{
"node": "webhook-response-error",
"type": "main",
"index": 0
}
]
]
}
}
}第 1 步:接收数据
第 2 步:验证数据
// 在「数据验证」节点中使用 Function Item
const data = $json;
const errors = [];
// 逐一检查必填字段
if (!data.name || data.name.trim() === '') {
errors.push('姓名不能为空');
}
// 返回验证结果
return {
isValid: errors.length === 0,
errors: errors,
data: { /* 清理后的数据 */ }
};第 3 步:条件分支
{{ $json.isValid === true }}第 4 步:返回结果
# 有效数据(通过验证)
curl -X POST https://your-webhook-url \
-H "Content-Type: application/json" \
-d '{
"name": "李四",
"email": "lisi@example.com",
"phone": "13800138000",
"age": 28
}'
# 无效数据(验证失败)
curl -X POST https://your-webhook-url \
-H "Content-Type: application/json" \
-d '{
"name": "",
"email": "invalid-email",
"phone": ""
}'| 用途 | 表达式 |
|---|---|
| 获取当前数据 | {{ $json }} |
| 获取特定字段 | {{ $json.fieldName }} |
| 条件判断 | {{ condition ? "是" : "否" }} |
| 默认值(null/undefined) | {{ $json.field ?? "默认" }} |
| 默认值(任何假值) | {{ $json.field || "默认" }} |
| 检查非空 | {{ $json.field !== undefined ? $json.field : "未提供" }} |
| 第一项数据 | {{ $input.first() }} |
| 最后一项数据 | {{ $input.last() }} |
| 所有项目 | {{ $input.all() }} |
| 转大写 | {{ $json.text.toUpperCase() }} |
| 转小写 | {{ $json.text.toLowerCase() }} |
| 检查数组长度 | {{ Array.isArray($json.items) ? $json.items.length : 0 }} |
| 当前时间戳 | {{ $now }} |
| 格式化日期 | {{ $now.toFormat("yyyy-MM-dd") }} |
通过本教程,你已经掌握了:
✅ 表达式的基础概念和语法
✅ 如何访问和验证数据
✅ 使用三元运算符进行条件判断
✅ 空值合并与逻辑运算符的区别
✅ 常见错误的排查方法
✅ 一个完整的实战工作流案例
[1] JSON 验证工具: https://jsonlint.com/
[2] 官方文档: https://docs.n8n.io/code/cookbook/expressions/
[3] n8n系列教程: https://www.undsky.com/blog/?category=n8n%E6%95%99%E7%A8%8B#