在日常工作中,我们经常需要处理 JSON 数据。无论是从 API 获取数据还是处理工作流中的中间结果,快速准确地提取和转换 JSON 数据都是必不可少的技能。
本教程将教你如何使用 JMESPath——一种功能强大的 JSON 查询语言——在 n8n 中轻松实现这一点。JMESPath 不仅能让你查询数据,还能帮你过滤、转换和聚合数据,而且代码简洁明了。
关键优势:相比复杂的 JavaScript 代码,JMESPath 语法更直观、更易学、更容易维护。
JMESPath 是一种为 JSON 设计的查询语言。它让你能够:
在 n8n 中,jmespath() 方法是一个原生的、高效的工具,可以在代码节点中使用,避免了繁琐的 JavaScript 循环和条件判断。
在 n8n 的代码节点中,你可以这样使用:
$jmespath(对象, "查询表达式")例子:
// 从对象中提取特定字段
const data = { name: "张三", age: 28, city: "北京" };
$jmespath(data, "name") // 结果: "张三"// 数据示例
const user = {
id: 1,
profile: {
name: "李四",
contact: {
email: "li@example.com"
}
}
};
// 使用点号访问嵌套字段
$jmespath(user, "profile.contact.email") // 结果: "li@example.com"这是 JMESPath 最强大的特性之一!
const people = [
{ firstName: "王", lastName: "五" },
{ firstName: "赵", lastName: "六" },
{ firstName: "孙", lastName: "七" }
];
// 提取所有人的名字
$jmespath(people, "[].firstName")
// 结果: ["王", "赵", "孙"]const employees = [
{ id: 101, name: "张三", salary: 8000 },
{ id: 102, name: "李四", salary: 9000 },
{ id: 103, name: "王五", salary: 8500 }
];
// 提取 id 和 name,创建新的对象数组
$jmespath(employees, "[].{id: id, name: name}")
// 结果: [
// { id: 101, name: "张三" },
// { id: 102, name: "李四" },
// { id: 103, name: "王五" }
// ]const products = [
{ id: 1, name: "笔记本", price: 5000, inStock: true },
{ id: 2, name: "鼠标", price: 80, inStock: false },
{ id: 3, name: "键盘", price: 200, inStock: true }
];
// 只获取有货的产品名称
$jmespath(products, "[?inStock == `true`].name")
// 结果: ["笔记本", "键盘"]
// 获取价格大于 100 的产品
$jmespath(products, "[?price > `100`].name")
// 结果: ["笔记本", "键盘"]提示:在 JMESPath 中,布尔值和数字需要用反引号包裹(如 `true`,`100`)。
场景:你收到一个复杂的 API 响应,只需要其中的用户邮箱列表。
原始数据:
{
"status": "success",
"data": {
"users": [
{ "id": 1, "email": "user1@example.com", "active": true },
{ "id": 2, "email": "user2@example.com", "active": false },
{ "id": 3, "email": "user3@example.com", "active": true }
]
}
}JMESPath 查询:
$jmespath(data, "data.users[].email")
// 结果: ["user1@example.com", "user2@example.com", "user3@example.com"]场景:你需要找出所有活跃用户,并为他们创建一个新的格式。
$jmespath(data, "data.users[?active == `true`].{userId: id, userEmail: email}")
// 结果:
// [
// { userId: 1, userEmail: "user1@example.com" },
// { userId: 3, userEmail: "user3@example.com" }
// ]const names = ["张三", "李四", "王五", "赵六", "孙七"];
// 获取前 3 个元素
$jmespath(names, "[0:3]")
// 结果: ["张三", "李四", "王五"]
// 获取最后 2 个元素
$jmespath(names, "[-2:]")
// 结果: ["赵六", "孙七"]除了代码节点,你还可以在 Set 节点 或其他支持表达式的节点中使用 JMESPath:
// 在 Set 节点的表达式中
{{ $jmespath($json, "data.users[?active == `true`][].email") }}当代码节点设置为 "Run Once for Each Item" 时:
// 处理单个数据项
const result = $jmespath($input.item.json, "user.profile.name");
return { json: { result } };当代码节点设置为 "Run Once for All Items" 时:
// 处理所有数据项
const allItems = $input.all();
const emails = $jmespath(allItems, "[].json.email");
return { json: { emails } };现在让我们创建一个完整的、可直接导入的工作流,展示如何使用 JMESPath 处理真实数据。
从 Webhook 接收产品数据,使用 JMESPath 提取并转换数据,最后保存结果。
{
"name": "JMESPath 数据提取示例",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "jmespath-demo",
"responseMode": "onReceived",
"options": {}
},
"id": "webhook",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [100, 100]
},
{
"parameters": {
"jsCode": "// 示例:从 webhook 数据中提取产品信息\nconst data = $input.item.json;\n\n// 使用 JMESPath 提取活跃产品\nconst activeProducts = $jmespath(\n data, \n \"products[?status == `active`].{id: id, name: name, price: price}\"\n);\n\n// 计算总价值\nconst totalValue = activeProducts.reduce((sum, p) => sum + p.price, 0);\n\nreturn {\n json: {\n productCount: activeProducts.length,\n products: activeProducts,\n totalValue: totalValue,\n processedAt: new Date().toISOString()\n }\n};"
},
"id": "code",
"name": "Code",
"type": "n8n-nodes-base.code",
"typeVersion": 1,
"position": [300, 100]
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
}
]
]
}
}
}向 Webhook 发送以下测试数据:
{
"products": [
{
"id": 1,
"name": "笔记本电脑",
"price": 5000,
"status": "active"
},
{
"id": 2,
"name": "鼠标",
"price": 80,
"status": "inactive"
},
{
"id": 3,
"name": "键盘",
"price": 200,
"status": "active"
},
{
"id": 4,
"name": "显示器",
"price": 1500,
"status": "active"
}
]
}预期输出:
{
"productCount": 3,
"products": [
{ "id": 1, "name": "笔记本电脑", "price": 5000 },
{ "id": 3, "name": "键盘", "price": 200 },
{ "id": 4, "name": "显示器", "price": 1500 }
],
"totalValue": 6700,
"processedAt": "2025-12-05T11:30:00.000Z"
}| 操作 | 表达式 | 示例 |
|---|---|---|
| 访问属性 | field | name |
| 嵌套属性 | parent.child | user.profile.email |
| 数组索引 | array[0] | users[0] |
| 列表投影 | array[].field | users[].name |
| 多选 | [].{field1: f1, field2: f2} | [].{id: id, name: name} |
| 过滤 | [?condition] | [?status == \active`]` |
| 切片 | [start:end] | [0:3] |
| 长度 | length(array) | length(users) |
| 排序 | sort(array) | sort(names) |
| 反转 | reverse(array) | reverse(items) |
// ❌ 错误
[?status == true] // 不能这样写
// ✅ 正确
[?status == `true`] // 使用反引号
[?price > `100`] // 数字也要用反引号// 如果属性名中有空格或特殊字符,使用引号
$jmespath(data, '"product-name"')
$jmespath(data, '"user name"')// 在表达式中,如果需要使用反引号,确保正确转义
// 在 n8n 表达式中: {{ $jmespath($json, "field[?value == \`test\`]") }}通过本教程,你已经掌握了:
✅ JMESPath 的基础语法
✅ 如何在 n8n 中使用 $jmespath() 方法
✅ 数组投影、过滤和多选等高级操作
✅ 实际工作流中的应用技巧
✅ 常见问题的解决方案
[1] 官方文档: https://docs.n8n.io/code/cookbook/jmespath/
[2] n8n系列教程: https://www.undsky.com/blog/?category=n8n%E6%95%99%E7%A8%8B#