• python中jmespath库用法详解


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

    官方文档:

    JMESPath — JMESPath

    JMESPath Examples — JMESPath

    安装

    pip install jmespath

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

    函数说明:

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

    1、获取键值对

    示例代码:

    1. import jmespath
    2. data = {
    3. "name": "张三",
    4. "age": 26,
    5. "gender": "男",
    6. "grade": {
    7. "Chinese": 96,
    8. "Math": 99
    9. },
    10. "records": [
    11. {
    12. "Chinese": 95,
    13. "Math": 100
    14. },
    15. {
    16. "Chinese": 98,
    17. "Math": 98
    18. }
    19. ]
    20. }
    21. # 获取键值对值
    22. search_cond = '{NAME:name, AGE:age, RECORDS:records}'
    23. res = jmespath.search(search_cond, data)
    24. print(res)

    运行结果:

     2、获取对象的值

     示例代码:

    1. import jmespath
    2. data = {
    3. "name": "张三",
    4. "age": 26,
    5. "gender": "男",
    6. "grade": {
    7. "Chinese": 96,
    8. "Math": 99
    9. },
    10. "records": [
    11. {
    12. "Chinese": 95,
    13. "Math": 100
    14. },
    15. {
    16. "Chinese": 98,
    17. "Math": 98
    18. }
    19. ]
    20. }
    21. # 获取对象值
    22. search_name = 'name'
    23. res_name = jmespath.search(search_name, data)
    24. print(res_name)
    25. search_records = 'records'
    26. res_records = jmespath.search(search_records, data)
    27. print(res_records)

    运行结果:

    3、子表达式取值

    示例代码:

    1. import jmespath
    2. data = {
    3. "name": "张三",
    4. "age": 26,
    5. "gender": "男",
    6. "grade": {
    7. "Chinese": 96,
    8. "Math": 99
    9. },
    10. "records": [
    11. {
    12. "Chinese": 95,
    13. "Math": 100
    14. },
    15. {
    16. "Chinese": 98,
    17. "Math": 98
    18. }
    19. ]
    20. }
    21. # 使用子表达式获取值,若值不存在返回null
    22. search_sub_value = 'grade.Chinese'
    23. res_sub_value = jmespath.search(search_sub_value, data)
    24. print(res_sub_value)
    25. search_sub_value1 = 'records[0].Chinese'
    26. res_sub_value1 = jmespath.search(search_sub_value1, data)
    27. print(res_sub_value1)
    28. search_sub_value2 = 'records[2].Chinese'
    29. res_sub_value2 = jmespath.search(search_sub_value2, data)
    30. print(res_sub_value2)

    运行结果:

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

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

    示例代码:

    1. import jmespath
    2. data = {
    3. "name": "张三",
    4. "age": 26,
    5. "gender": "男",
    6. "grade": {
    7. "Chinese": 96,
    8. "Math": 99
    9. },
    10. "records": [
    11. {
    12. "Chinese": 95,
    13. "Math": 100
    14. },
    15. {
    16. "Chinese": 98,
    17. "Math": 98
    18. }
    19. ]
    20. }
    21. # 列表取值,索引从0开始,若是
    22. search_list1 = 'records[1].Chinese'
    23. res_list1 = jmespath.search(search_list1, data)
    24. print(res_list1)
    25. search_list2 = 'records[2].Chinese'
    26. res_list2 = jmespath.search(search_list2, data)
    27. print(res_list2)
    28. search_list3 = 'records[-1].Chinese'
    29. res_list3 = jmespath.search(search_list3, data)
    30. print(res_list3)

    运行结果:

    5、切片

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

    示例代码:

    1. import jmespath
    2. data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    3. ret1 = jmespath.search("[0:5]", data)
    4. print(ret1)
    5. ret2 = jmespath.search("[5:10]", data)
    6. print(ret2)
    7. ret3 = jmespath.search("[::2]", data)
    8. print(ret3)

    运行结果:

    6、列表投影

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

    示例代码:

    1. import jmespath
    2. data = {
    3. "student": [
    4. {"name": "james", "age": 32},
    5. {"name": "harden", "age": 18},
    6. {"name": "curry", "age": 13},
    7. {"test": "ok"}
    8. ]
    9. }
    10. ret1 = jmespath.search("student[*]", data)
    11. print(ret1)
    12. ret2 = jmespath.search("student[*].name", data)
    13. print(ret2)
    14. # 切片投影
    15. ret3 = jmespath.search("student[:2].name", data)
    16. print(ret3)

    运行结果:

    7、对象投影

    示例代码:

    1. import jmespath
    2. data = {
    3. "test": {
    4. "funcA": {"num": 1},
    5. "funcB": {"num": 2},
    6. "funcC": {"miss": 3},
    7. }
    8. }
    9. ret1 = jmespath.search("test.*", data)
    10. print(ret1)
    11. ret2 = jmespath.search("test.*.num", data)
    12. print(ret2)

    运行结果:

    8、展平投影

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

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

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

    示例代码:

    1. import jmespath
    2. data = {
    3. "a": [
    4. {
    5. "b": [
    6. {"name": "a"},
    7. {"name": "b"}
    8. ]
    9. },
    10. {
    11. "b": [
    12. {"name": "c"},
    13. {"name": "d"}
    14. ]
    15. }
    16. ]
    17. }
    18. ret1 = jmespath.search("a[*].b[*].name", data)
    19. print(ret1)
    20. ret2 = jmespath.search("a[*].b[].name", data)
    21. print(ret2)
    22. ret3 = jmespath.search("a[].b[].name", data)
    23. print(ret3)
    24. ret4 = jmespath.search("a[].b[*].name", data)
    25. print(ret4)
    26. ret5 = jmespath.search("a[].b[]", data)
    27. print(ret5)

    运行结果:

    9、过滤投影

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

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

    条件表达式支持如下:

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

    示例代码:

    1. import jmespath
    2. data = {
    3. "book": [
    4. {"name": "a1", "author": "aa"},
    5. {"name": "a2", "author": "aa"},
    6. {"name": "b", "author": "bb"}
    7. ]
    8. }
    9. ret1 = jmespath.search("book[?author=='aa'].name", data)
    10. print(ret1)

    运行结果:

    10、管道表达式

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

    示例代码:

    1. import jmespath
    2. data = {
    3. "book": [
    4. {"name": "a1", "author": "aa"},
    5. {"name": "a2", "author": "aa"},
    6. {"name": "b", "author": "bb"}
    7. ]
    8. }
    9. ret1 = jmespath.search("book[*].name", data)
    10. print(ret1)
    11. ret2 = jmespath.search("book[*].name | [1]", data)
    12. print(ret2)

    运行结果:

    11、多选列表

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

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

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

    示例代码:

    1. import jmespath
    2. data = {
    3. "people": [
    4. {
    5. "name": "a",
    6. "state": {"name": "up"}
    7. },
    8. {
    9. "name": "b",
    10. "state": {"name": "down"}
    11. },
    12. {
    13. "name": "c",
    14. "state": {"name": "up"}
    15. }
    16. ]
    17. }
    18. ret = jmespath.search("people[].[name, state.name]", data)
    19. print(ret)

    运行结果:

    12、多选对象

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

    示例代码:

    1. import jmespath
    2. data = {
    3. "people": [
    4. {
    5. "name": "a",
    6. "state": {"name": "up"}
    7. },
    8. {
    9. "name": "b",
    10. "state": {"name": "down"}
    11. },
    12. {
    13. "name": "c",
    14. "state": {"name": "up"}
    15. }
    16. ]
    17. }
    18. ret = jmespath.search("people[].{name: name, state_name: state.name}", data)
    19. print(ret)

    运行结果:

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

    示例代码:

    1. import jmespath
    2. class TestJmesPath(object):
    3. def __init__(self):
    4. self.data = {
    5. "book": [
    6. {"name": "平凡的世界", "author": "路遥", "sort": 3},
    7. {"name": "围城", "author": "钱钟书", "sort": 2},
    8. {"name": "围城", "author": "钱钟书", "sort": 2},
    9. {"name": "活着", "author": "余华", "sort": 1},
    10. {"name": "麦田里的守望者", "author": "塞林格", "sort": 4},
    11. {"name": "挪威的森林", "author": "村上春树", "sort": 5}
    12. ]
    13. }
    14. def test_keys(self):
    15. """提取对象的 key """
    16. result = jmespath.search("book[0].name", self.data)
    17. return result
    18. def test_values(self):
    19. """提取对象的 value,不接受数组"""
    20. result = jmespath.search("book[0] | values(@)", self.data)
    21. return result
    22. def test_sort(self):
    23. """根据 sort 进行排序"""
    24. result = jmespath.search("book[*].sort | sort(@)", self.data)
    25. return result
    26. def test_sort2(self):
    27. result = jmespath.search("book[*].author | sort(@) | [join(', ', @)]", self.data)
    28. return result
    29. def test_type(self):
    30. result = jmespath.search("book[*].name | type(@)", self.data)
    31. return result
    32. def test_type2(self):
    33. result = jmespath.search("book[0].name | type(@)", self.data)
    34. return result
    35. def test_to_string(self):
    36. result = jmespath.search('[].to_string(@)', [1, 2, 3, "number", True])
    37. return result
    38. def test_to_number(self):
    39. result = jmespath.search('[].to_number(@)', ["1", "2", "3", "number", True])
    40. return result
    41. def test_contains(self):
    42. result = jmespath.search("contains(`foobar`, `foo`)", {})
    43. return result
    44. def test_contains2(self):
    45. result = jmespath.search("contains(`foobar`, `f123`)", {})
    46. return result
    47. def test_join(self):
    48. # expected one of: ['array-string']
    49. # @ 为当前节点,得到的结果用逗号加空格分隔,然后放在当前节点下
    50. result = jmespath.search("join(`, `, @)", ["a", "b"])
    51. return result
    52. def test_length(self):
    53. result = jmespath.search("length(@)", ["a", "b"])
    54. return result
    55. def test_max(self):
    56. result = jmespath.search("max(@)", [10, 3, 5, 5, 8])
    57. return result
    58. def test_min(self):
    59. result = jmespath.search("min(@)", [10, 3, 5, 5, 8])
    60. return result
    61. if __name__ == '__main__':
    62. obj = TestJmesPath()
    63. print(obj.test_keys())
    64. print(obj.test_values())
    65. print(obj.test_sort())
    66. print(obj.test_sort2())
    67. print(obj.test_type())
    68. print(obj.test_type2())
    69. print(obj.test_to_string())
    70. print(obj.test_to_number())
    71. print(obj.test_contains())
    72. print(obj.test_contains2())
    73. print(obj.test_join())
    74. print(obj.test_length())
    75. print(obj.test_max())
    76. print(obj.test_min())

    运行结果:

    14、自定义函数

    示例代码:

    1. from jmespath import search
    2. from jmespath import functions
    3. import jmespath
    4. class CustomFunctions(functions.Functions):
    5. @functions.signature({'types': ['string', "array"]})
    6. def _func_uniq(self, arg):
    7. if isinstance(arg, str):
    8. # string of unique
    9. return ''.join(sorted(set(arg)))
    10. if isinstance(arg, list):
    11. # array of unique
    12. return sorted(set(arg))
    13. options = jmespath.Options(custom_functions=CustomFunctions())
    14. aa = search("foo.bar", {'foo': {'bar': 'banana'}})
    15. print(aa)
    16. bb = search("foo.bar | uniq(@)", {'foo': {'bar': 'banana'}}, options=options)
    17. print(bb)
    18. cc = search("foo.bar", {'foo': {'bar': [5, 5, 2, 1]}})
    19. print(cc)
    20. dd = search("foo.bar | uniq(@)", {'foo': {'bar': [5, 5, 2, 1]}}, options=options)
    21. print(dd)

    运行结果:

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

    示例代码:

    1. import jmespath
    2. data = {
    3. "name": ['张三', '李四', '张三丰', '王五']
    4. }
    5. ret = jmespath.search("name[?contains(@, '张')]", data)
    6. print(ret)

    运行结果:

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

    示例代码:

    1. import jmespath
    2. data = {
    3. "people": [{"name": "张三", 'age': 25}, {"name": "李四", 'age': 26}, {"name": "王五", 'age': 23}]
    4. }
    5. ret = jmespath.search("sort_by(people, &age)", data)
    6. print(ret)

    运行结果:

    参考博文:

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

  • 相关阅读:
    日化用品行业集团采购管理系统改变传统采购模式,降低采购成本
    TypeScript
    Taurus.MVC WebAPI 入门开发教程1:框架下载环境配置与运行(含系列目录)。
    (vue)el-select根据下拉框显示隐藏的visible-change的事件使用
    【计算机网络】网络模型
    简单介绍一下tensorflow与pytorch的相互转换(主要是tensorflow转pytorch)
    《模式识别》教学上机实验报告
    【864. 获取所有钥匙的最短路径】
    用JAVA编写商城的好处
    Git 详细教程之五:SSH 免密登陆 GitHub
  • 原文地址:https://blog.csdn.net/weixin_44799217/article/details/127590589