侧边栏壁纸
博主头像
一朵云的博客博主等级

拥抱生活,向阳而生。

  • 累计撰写 107 篇文章
  • 累计创建 28 个标签
  • 累计收到 7 条评论

目 录CONTENT

文章目录

Python -- JMESPath 库的介绍与使用

一朵云
2024-04-10 / 0 评论 / 0 点赞 / 135 阅读 / 8320 字

Python -- JMESPath 库的介绍与使用

简介:

是一种用于查询和提取 JSON 数据的查询语言。它的设计目标是让开发者能够以简洁、可读性强的方式从复杂的 JSON 结构中提取所需的数据。

你可以把它理解为 JSON 的“SQL”或“XPath”:就像 SQL 查询数据库、XPath 查询 XML 一样,JMESPath 专门用于查询 JSON。

​ 

​ 

如:

{
  "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`]

image-fjiu.png

语法:

基础操作符

操作符 说明
. 访问对象属性
[] 数组访问或投影
* 通配符(所有元素)
[?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 → 数字 3000
  • true → 布尔值 true
  • null → 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做断言挺好的,可以节省很多逻辑判断。

0

评论区