Python -- JMESPath 库的介绍与使用
简介:
是一种用于查询和提取 JSON 数据的查询语言。它的设计目标是让开发者能够以简洁、可读性强的方式从复杂的 JSON 结构中提取所需的数据。
你可以把它理解为 JSON 的“SQL”或“XPath”:就像 SQL 查询数据库、XPath 查询 XML 一样,JMESPath 专门用于查询 JSON。
- https://jmespath.org/ 官方在线练习地址
- https://play.jmespath.org/ 功能更全(由社区维护)
如:
{
"company": {
"ceo": { "age": 50 },
"employees": [
{ "name": "A", "age": 30, "monthly_salary": 3000, "performance_bonus": 5000 },
{ "name": "B", "age": 32, "monthly_salary": 6000, "performance_bonus": 5000 },
{ "name": "C", "age": 34, "monthly_salary": 13000, "performance_bonus": 8000 },
{ "name": "D", "age": 51, "monthly_salary": 20000, "performance_bonus": 5000 },
{ "name": "E", "age": 25, "monthly_salary": 7000, "performance_bonus": 10000 }
]
}
}
找出月薪超过8000的用户:
company.employees[?monthly_salary > `8000`]
语法:
基础操作符
操作符 | 说明 |
---|---|
. |
访问对象属性 |
[] |
数组访问或投影 |
* |
通配符(所有元素) |
[?expr] |
过滤表达式 |
{} |
创建新对象(重命名字段) |
@ |
当前节点引用 |
投影:
能力 | 说明 | 示例 |
---|---|---|
1️⃣ 提取(Extract) | 拿出你关心的字段 | users[*].name → ["张三", "李四"] |
2️⃣ 重塑(Reshape) | 改变结构,创建新对象 | users[*].{姓名: name} → [{"姓名":"张三"}] |
3️⃣ 转换(Transform) | 过滤、计算、重组 | users[?age > 25][*].name → 年龄>25的人名 |
示例:
{
"orders": [
{
"id": "A001",
"customer": { "name": "张三", "level": "VIP" },
"amount": 299,
"status": "shipped"
},
{
"id": "A002",
"customer": { "name": "李四", "level": "普通" },
"amount": 99,
"status": "pending"
}
]
}
1、提取:
提取json串中的所有id
orders[*].id
结果:["A001", "A002"]
2、重塑:
提取json串中的所有的id、customer.name、amount的值,并修改key值为中文名作为新json。
orders[*].{订单号: id, 客户: customer.name, 金额: amount}
结果:
[
{ "订单号": "A001", "客户": "张三", "金额": 299 },
{ "订单号": "A002", "客户": "李四", "金额": 99 }
]
3、转换:
提取json串中,amount值大于100的用户id和名称,组个新串。
orders[?amount > 100].[id, customer.name]
结果:
[
["A001", "张三"]
]
总结:
投影是从原 JSON 中,通过 JMESPath 表达式,提取、过滤、重塑出一个你想要的新 JSON 结构——它可能是子集,也可能是全新形态。
@ 操作符
解释: @
的核心作用是:明确“当前是谁”,尤其在“上下文混乱”或“需要自比较”的时候,它是你的“锚点”。
啥时候可以省略:
1、简单字段过滤
users[?age > `25`]
等价于
users[?@.age > `25`]
2、简单投影
users[*].name
等价于
users[*].@.name
啥时候需要写?
1、两个字段比较
users[?@.username != @.nickname]
2、函数调用中传字段
users[?length(@.tags) > 3]
3、调试时打印当前对象
users[?age > 25].@
解释:
第1、2调用时,不加@,在python中我试了也能编译通过,也就第3步好用。
准备:
如果在python中使用的话需要提前安装依赖库
pip install jmespath
Python编译器中操作
使用 JMESPath 的 字面量语法 `value`
在 JMESPath 规范中,反引号 ` 用于包裹字面量(literal) ,否则可能识别不出,可以明确表示:
3000
→ 数字 3000true
→ 布尔值 truenull
→ null
实操1
将python变量size放进表达式
def test_jmespath():
data = [{"length": 10, "size": 15}]
size = 2
# data json串中的length字段 与 python的变量size字段对比
expr = f"[?length > `{size}`]"
result = jmespath.search(expr, data)
# 格式化输出
print(f"\n{json.dumps(result, indent=2, ensure_ascii=False)}")
结果:
test_demo.py::test_jmespath PASSED [100%]
[
{
"length": 10,
"size": 15
}
]
实操2
表达式中对比数字
def test_jmespath():
data = [{"length": 10, "size": 15}, {"length": 5, "size": 10}]
expr = f"[?length > `9`]"
result = jmespath.search(expr, data)
# 格式化输出
print(f"\n{json.dumps(result, indent=2, ensure_ascii=False)}")
结果:
test_demo.py::test_jmespath PASSED [100%]
[
{
"length": 10,
"size": 15
}
]
JMESPath 函数
函数 | 说明 |
---|---|
length() |
数组长度、对象 key 数量 |
sum() |
数组求和 |
avg() |
数组平均值 |
max() / min() |
最大/最小值 |
contains() |
是否包含(字符串、数组) |
starts_with() / ends_with() |
字符串前缀/后缀判断 |
to_string() / to_number() / to_array() |
类型转换 |
keys() / values() |
获取对象的 key 或 value |
sort() / sort_by() |
排序 |
reverse() |
反转数组 |
type() |
返回值的类型 |
结语:
这个JMESPath库效率比Jsonpath_ng的效率高,这些基本函数搭配自定义DSL做断言挺好的,可以节省很多逻辑判断。
评论区