jmespath库的功能和jsonpath比较相似, 以前不知到这个,他们都是用来从json中抽取数据的
参考:其中有4篇文章介绍jmespath
https://www.cnblogs.com/pingguo-softwaretesting/category/1789411.html
作者还有一部分没有讲到,那就过滤器
这个页面中,可以学习怎么使用jmespath,可以在学习的过程进行练习, https://jmespath.org/tutorial.html [英文的]
这里仅记录下第一个连接中未介绍的部分,其他请参考上面的2个链接吧。
对投影进行过滤:【仅能用于过滤list】
表达能力比较弱,还是举例子吧
{
"machines": [
{"name": "a", "state": "running"},
{"name": "b", "state": "stopped"},
{"name": "c", "state": "running"}
]
}
表达式: machines[?state=='running'].name
结果为:[ "a", "c" ]
表达式: machines[?state=='running']
结果为:
[
{
"name": "a",
"state": "running"
},
{
"name": "c",
"state": "running"
}
]
上面的代码示例,说明我们可以通过 LHS [? <expression> <comparator> <expression>] RHS 的格式来对list中的值进行过滤。
表达式中去掉name后,就是我们的过滤器产生的完整的结果
过滤表达式中的可以使用的操作符包括: ==, !=, <, <=, >, >=.
管道表达式
有一个问题需要jmespath帮我们解决。
{
"people": [
{"first": [1,2]},
{"first": [3,4]},
{"first": [5,6]},
{"missing": "different"}
],
"foo": {"bar": "baz"}
}
目的:我想获取第二个first下对应的值
表达式: people[*].first[1]
结果:
[
2,
4,
6
]
这是因为[1]并不是去获取第二个first下对应的值,而是对所有的first的值都取索引1对应的值
-----------------------------------------------------------------------------------------
使用管道可以解决这个问题!!
表达式: people[*].first | [0]
| 是管道符, 告诉jmespath,投影操作到此为止,此时投影的结果作为一个新的数据开始进行取值操作了
结果:
[
1,
2
]
生成新的列表或字典
以上我们学习到的,都仅仅是数据的抽取,或者投影(转换成list)
jmespath可以让我们,根据需要生成新的list或者dict
例子1: 我们根据原始数据生成一组新的list
{
"people": [
{
"name": "a",
"state": {"name": "up"}
},
{
"name": "b",
"state": {"name": "down"}
},
{
"name": "c",
"state": {"name": "up"}
}
]
}
表达式: people[].[name, state.name]
结果:
[
[
"a",
"up"
],
[
"b",
"down"
],
[
"c",
"up"
]
]
表达式: people[].[name, state.name1]
结果:
[
[
"a",
None
],
[
"b",
None
],
[
"c",
None
]
]
需要注意的是,即使没有找到name,或者state.name 那么结果也不会是空列表,会用None填充
例子2: 我们根据原始数据生成一组新的dict
{
"people": [
{
"name": "a",
"state": {"name": "up"}
},
{
"name": "b",
"state": {"name": "down"}
},
{
"name": "c",
"state": {"name": "up"}
}
]
}
表达式: people[].{Name: name, State: state.name}
结果:
[
{
"Name": "a",
"State": "up"
},
{
"Name": "b",
"State": "down"
},
{
"Name": "c",
"State": "up"
}
]
使用函数
JMESPath可以支持函数表达式,buildin的函数,可以从这里找到 buildin
{
"people": [
{
"name": "Simon",
"age": 30,
"state": {"name": "up"}
},
{
"name": "wenson",
"age": 50,
"state": {"name": "down"}
},
{
"name": "bigben",
"age": 40,
"state": {"name": "up"}
}
]
}
表达式:length(people)
结果: 3
表达式:max_by(people, &age).name
结果: "wenson"
表达式:people[?contains(name, 'on') == `true`].name
结果:
[
"Simon",
"wenson"
]
{
"myarray": [
"foo",
"foobar",
"barfoo",
"bar",
"baz",
"barbaz",
"barfoobaz"
]
}
表达式: myarray[?contains(@, 'foo') == `true`]
结果:
[
"foo",
"foobar",
"barfoo",
"barfoobaz"
]
这个@好像仅能用在列表项是字符串的情况,如果列表项是dict那么需要指定要进行比较的key
@代表列表中所有的项