python中jmespath库用法详解
  TEZNKK3IfmPf 2023年11月14日 23 0

        JMESPath 是 JSON 查询语言,可以从 JSON 文档中提取和转换元素。在做接口自动化测试项目时,最基础的一步就是从响应中获取各种待验证的字段值,掌握 jmespath 语法,能达到事半功倍的效果。

官方文档:

JMESPath — JMESPath

JMESPath Examples — JMESPath

安装

pip install jmespath

python中jmespath库用法详解

jmespath.py 库提供了两个接口:

python中jmespath库用法详解

函数说明:

  • compile:与 re 模块类似,使用 compile 函数编译表达式,并使用解析后的表达式执行重复搜索
  • search:接收表达式和数据,返回提取结果

1、获取键值对

示例代码:

import jmespath

data = {
    "name": "张三",
    "age": 26,
    "gender": "男",
    "grade": {
        "Chinese": 96,
        "Math": 99
    },
    "records": [
        {
            "Chinese": 95,
            "Math": 100
        },
        {
            "Chinese": 98,
            "Math": 98
        }
    ]
}

# 获取键值对值
search_cond = '{NAME:name, AGE:age, RECORDS:records}'
res = jmespath.search(search_cond, data)
print(res)

运行结果:

python中jmespath库用法详解

 2、获取对象的值

 示例代码:

import jmespath

data = {
    "name": "张三",
    "age": 26,
    "gender": "男",
    "grade": {
        "Chinese": 96,
        "Math": 99
    },
    "records": [
        {
            "Chinese": 95,
            "Math": 100
        },
        {
            "Chinese": 98,
            "Math": 98
        }
    ]
}

# 获取对象值
search_name = 'name'
res_name = jmespath.search(search_name, data)
print(res_name)

search_records = 'records'
res_records = jmespath.search(search_records, data)
print(res_records)

运行结果:

python中jmespath库用法详解

3、子表达式取值

示例代码:

import jmespath

data = {
    "name": "张三",
    "age": 26,
    "gender": "男",
    "grade": {
        "Chinese": 96,
        "Math": 99
    },
    "records": [
        {
            "Chinese": 95,
            "Math": 100
        },
        {
            "Chinese": 98,
            "Math": 98
        }
    ]
}

# 使用子表达式获取值,若值不存在返回null
search_sub_value = 'grade.Chinese'
res_sub_value = jmespath.search(search_sub_value, data)
print(res_sub_value)


search_sub_value1 = 'records[0].Chinese'
res_sub_value1 = jmespath.search(search_sub_value1, data)
print(res_sub_value1)

search_sub_value2 = 'records[2].Chinese'
res_sub_value2 = jmespath.search(search_sub_value2, data)
print(res_sub_value2)

运行结果:

python中jmespath库用法详解

4、列表取值(对象嵌套列表)

        索引表达式,从 0 开始,索引越界,则返回 null;索引可以为负数,-1 为列表中最后一个元素。

示例代码:

import jmespath

data = {
    "name": "张三",
    "age": 26,
    "gender": "男",
    "grade": {
        "Chinese": 96,
        "Math": 99
    },
    "records": [
        {
            "Chinese": 95,
            "Math": 100
        },
        {
            "Chinese": 98,
            "Math": 98
        }
    ]
}

# 列表取值,索引从0开始,若是
search_list1 = 'records[1].Chinese'
res_list1 = jmespath.search(search_list1, data)
print(res_list1)

search_list2 = 'records[2].Chinese'
res_list2 = jmespath.search(search_list2, data)
print(res_list2)

search_list3 = 'records[-1].Chinese'
res_list3 = jmespath.search(search_list3, data)
print(res_list3)

运行结果:

python中jmespath库用法详解

5、切片

        与 python 列表切片相同,[start:end:step],留头掐尾

示例代码:

import jmespath

data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

ret1 = jmespath.search("[0:5]", data)
print(ret1)

ret2 = jmespath.search("[5:10]", data)
print(ret2)

ret3 = jmespath.search("[::2]", data)
print(ret3)

运行结果:

python中jmespath库用法详解

6、列表投影

        通配符 *,表示返回列表中的全部元素。当单组元素的结果表达式为 null,则该值从收集的 结果集 中忽略。

示例代码:

import jmespath

data = {
    "student": [
        {"name": "james", "age": 32},
        {"name": "harden", "age": 18},
        {"name": "curry", "age": 13},
        {"test": "ok"}
    ]
}

ret1 = jmespath.search("student[*]", data)
print(ret1)

ret2 = jmespath.search("student[*].name", data)
print(ret2)

# 切片投影
ret3 = jmespath.search("student[:2].name", data)
print(ret3)

运行结果:

python中jmespath库用法详解

7、对象投影

示例代码:

import jmespath

data = {
    "test": {
        "funcA": {"num": 1},
        "funcB": {"num": 2},
        "funcC": {"miss": 3},
    }
}

ret1 = jmespath.search("test.*", data)
print(ret1)

ret2 = jmespath.search("test.*.num", data)
print(ret2)

运行结果:

python中jmespath库用法详解

8、展平投影

        列表/对象投影,在投影中创建投影时会保留原始文档的结构。

        如果只要列表下的所有值,不关心所谓的层级结构,那么就需要通过展平投影来获取结果。

        只需要将 [*] -> [] 就可以扁平化列表。它将子列表展平到父列表,并不是递归的关系

示例代码:

import jmespath

data = {
  "a": [
    {
      "b": [
        {"name": "a"},
        {"name": "b"}
      ]
    },
    {
      "b": [
        {"name": "c"},
        {"name": "d"}
      ]
    }
  ]
}

ret1 = jmespath.search("a[*].b[*].name", data)
print(ret1)

ret2 = jmespath.search("a[*].b[].name", data)
print(ret2)

ret3 = jmespath.search("a[].b[].name", data)
print(ret3)

ret4 = jmespath.search("a[].b[*].name", data)
print(ret4)

ret5 = jmespath.search("a[].b[]", data)
print(ret5)

运行结果:

python中jmespath库用法详解

9、过滤投影

        过滤器表达式是为数组定义的,一般形式为:

左侧投影 [? <表达式> <比较器> <表达式>] 右侧投影

条件表达式支持如下:

  • ==, tests for equality.
  • !=, tests for inequality.
  • <, less than.
  • <=, less than or equal to.
  • >, greater than.
  • >=, greater than or equal to.

示例代码:

import jmespath

data = {
  "book": [
    {"name": "a1", "author": "aa"},
    {"name": "a2", "author": "aa"},
    {"name": "b", "author": "bb"}
  ]
}

ret1 = jmespath.search("book[?author=='aa'].name", data)
print(ret1)

运行结果:

python中jmespath库用法详解

10、管道表达式

        管道表达式 <expression> | <expression>,表示必须停止投影。将当前节点的结果传递到管道符右侧继续投影。

示例代码:

import jmespath

data = {
  "book": [
    {"name": "a1", "author": "aa"},
    {"name": "a2", "author": "aa"},
    {"name": "b", "author": "bb"}
  ]
}

ret1 = jmespath.search("book[*].name", data)
print(ret1)

ret2 = jmespath.search("book[*].name | [1]", data)
print(ret2)

运行结果:

python中jmespath库用法详解

11、多选列表

[name, state.name] 表达式的意思是创建一个包含两个元素的列表:

  • 第一个元素是计算 name 表达式得到的结果
  • 第二个元素是计算 state.name 表达式的结果

        因此,每个列表元素都会创建一个双元素列表,整个表达式的最终结果是一个包含两个元素列表的列表。

示例代码:

import jmespath

data = {
  "people": [
    {
      "name": "a",
      "state": {"name": "up"}
    },
    {
      "name": "b",
      "state": {"name": "down"}
    },
    {
      "name": "c",
      "state": {"name": "up"}
    }
  ]
}

ret = jmespath.search("people[].[name, state.name]", data)
print(ret)

运行结果:

python中jmespath库用法详解

12、多选对象

        与多选列表思想相同,创建的是一个散列而不是数组。

示例代码:

import jmespath

data = {
  "people": [
    {
      "name": "a",
      "state": {"name": "up"}
    },
    {
      "name": "b",
      "state": {"name": "down"}
    },
    {
      "name": "c",
      "state": {"name": "up"}
    }
  ]
}

ret = jmespath.search("people[].{name: name, state_name: state.name}", data)
print(ret)

运行结果:

python中jmespath库用法详解

13、函数的使用(包含常用的一些内置函数)

示例代码:

import jmespath


class TestJmesPath(object):

    def __init__(self):
        self.data = {
            "book": [
                {"name": "平凡的世界", "author": "路遥", "sort": 3},
                {"name": "围城", "author": "钱钟书", "sort": 2},
                {"name": "围城", "author": "钱钟书", "sort": 2},
                {"name": "活着", "author": "余华", "sort": 1},
                {"name": "麦田里的守望者", "author": "塞林格", "sort": 4},
                {"name": "挪威的森林", "author": "村上春树", "sort": 5}
            ]
        }

    def test_keys(self):
        """提取对象的 key """
        result = jmespath.search("book[0].name", self.data)
        return result

    def test_values(self):
        """提取对象的 value,不接受数组"""
        result = jmespath.search("book[0] | values(@)", self.data)
        return result

    def test_sort(self):
        """根据 sort 进行排序"""
        result = jmespath.search("book[*].sort | sort(@)", self.data)
        return result

    def test_sort2(self):
        result = jmespath.search("book[*].author | sort(@) | [join(', ', @)]", self.data)
        return result

    def test_type(self):
        result = jmespath.search("book[*].name | type(@)", self.data)
        return result

    def test_type2(self):
        result = jmespath.search("book[0].name | type(@)", self.data)
        return result

    def test_to_string(self):
        result = jmespath.search('[].to_string(@)', [1, 2, 3, "number", True])
        return result

    def test_to_number(self):
        result = jmespath.search('[].to_number(@)', ["1", "2", "3", "number", True])
        return result

    def test_contains(self):
        result = jmespath.search("contains(`foobar`, `foo`)", {})
        return result

    def test_contains2(self):
        result = jmespath.search("contains(`foobar`, `f123`)", {})
        return result

    def test_join(self):
        # expected one of: ['array-string']
        # @ 为当前节点,得到的结果用逗号加空格分隔,然后放在当前节点下
        result = jmespath.search("join(`, `, @)", ["a", "b"])
        return result

    def test_length(self):
        result = jmespath.search("length(@)", ["a", "b"])
        return result

    def test_max(self):
        result = jmespath.search("max(@)", [10, 3, 5, 5, 8])
        return result

    def test_min(self):
        result = jmespath.search("min(@)", [10, 3, 5, 5, 8])
        return result


if __name__ == '__main__':
    obj = TestJmesPath()
    print(obj.test_keys())
    print(obj.test_values())
    print(obj.test_sort())
    print(obj.test_sort2())
    print(obj.test_type())
    print(obj.test_type2())
    print(obj.test_to_string())
    print(obj.test_to_number())
    print(obj.test_contains())
    print(obj.test_contains2())
    print(obj.test_join())
    print(obj.test_length())
    print(obj.test_max())
    print(obj.test_min())

运行结果:

python中jmespath库用法详解

14、自定义函数

示例代码:

from jmespath import search
from jmespath import functions
import jmespath


class CustomFunctions(functions.Functions):

    @functions.signature({'types': ['string', "array"]})
    def _func_uniq(self, arg):
        if isinstance(arg, str):
            # string of unique
            return ''.join(sorted(set(arg)))
        if isinstance(arg, list):
            # array of unique
            return sorted(set(arg))


options = jmespath.Options(custom_functions=CustomFunctions())

aa = search("foo.bar", {'foo': {'bar': 'banana'}})
print(aa)

bb = search("foo.bar | uniq(@)", {'foo': {'bar': 'banana'}}, options=options)
print(bb)

cc = search("foo.bar", {'foo': {'bar': [5, 5, 2, 1]}})
print(cc)

dd = search("foo.bar | uniq(@)", {'foo': {'bar': [5, 5, 2, 1]}}, options=options)
print(dd)

运行结果:

python中jmespath库用法详解

15、包含:contains(@, 'foo'),@关联到当前级别的元素值

示例代码:

import jmespath

data = {
    "name": ['张三', '李四', '张三丰', '王五']
}

ret = jmespath.search("name[?contains(@, '张')]", data)
print(ret)

运行结果:

python中jmespath库用法详解

16、排序:sort_by(contents, &Date)

示例代码:

import jmespath

data = {
    "people": [{"name": "张三", 'age': 25}, {"name": "李四", 'age': 26}, {"name": "王五", 'age': 23}]
}

ret = jmespath.search("sort_by(people, &age)", data)
print(ret)

运行结果:

python中jmespath库用法详解

参考博文:

JMESPath 基本操作_abee-tester的博客-CSDN博客_jmespath

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月14日 0

暂无评论

推荐阅读
  TEZNKK3IfmPf   2024年05月31日   32   0   0 python开发语言
  TEZNKK3IfmPf   2024年05月31日   25   0   0 python
  TEZNKK3IfmPf   2024年05月31日   34   0   0 excelpython
  TEZNKK3IfmPf   2024年05月31日   25   0   0 python
TEZNKK3IfmPf