自动化工具 jmespath 使用- 可以替代 python jsonpath

simonpatrick · 2018年08月13日 · 最后由 生存以上 回复于 2021年09月25日 · 4166 次阅读

今天一直被 35 岁的问题困扰,感觉相当不好;刚好看到一个介绍 jmespath 的工具,感觉相当不错,怒分享.虽然按照 35 岁里面说的要接受被淘汰的命运,但是还是觉得做一天和尚就干好一天的事情,听天命,尽人事,所以觉得有不错的东西就动手试试,分享分享。

在测试过程中,经常会去 JSON 中的某个值,jmespath可以是除了 jsonpath 的另外一种选择.
下面通过几个例子来说明 jmespath 在 python 的使用

jmespath python 安装

非常简单直接 pip,

pip install jmespth

查询一个 key 值

source={"a": "foo", "b": "bar", "c": "baz"}
result = jmespath.search("a",source)
print(result)

subexpression

类似于 jsonpath,通过.来表示路径的层级

source_1={"a": {"b": {"c": {"d": "value"}}}}
sub_result = jmespath.search("a.b.c",source_1)
print(sub_result)

这个例子的结果为:{'d': 'value'}

index expressions

index expression 主要使用在数组上

source_2 = ["a", "b", "c", "d", "e", "f"]
index_result = jmespath.search("[1]",source_2)
print(index_result)

这个例子的结果为:b

多个表达式综合使用

以上几种表达式可以合起来一期使用:

composite_exp = "a.b.c[0].d[1][0]"
source_3= {"a": {
  "b": {
    "c": [
      {"d": [0, [1, 2]]},
      {"d": [3, 4]}
    ]
  }
}}

composite_result = jmespath.search(composite_exp,source_3)
print(composite_result)

这个例子的结果为 1

Slicing 切片

slicing 和 python 本身的 slicing 比较像,

source_4=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
slicing_exp = "[0:5]"
slicing_result = jmespath.search(slicing_exp,source_4)
print(slicing_result)

这个例子的结果为: [0, 1, 2, 3, 4]

slicing 实际上和 python 自己的机制基本一样,同样这个也是主要给数组使用.
有一点需要记住,基本的 slicing 的格式其实是: [start:stop:step]

Projections

projection 不知道怎么翻译,就先叫做投影吧,具体通过例子来说比较好理解.
projections 主要包含一下几种情况:

  • List Projections
  • Slice Projections
  • Object Projections
  • Flatten Projections
  • Filter Projections

Projections- 例子

list_exp="people[*].first"
source_5 = {
  "people": [
    {"first": "James", "last": "d"},
    {"first": "Jacob", "last": "e"},
    {"first": "Jayden", "last": "f"},
    {"missing": "different"}
  ],
  "foo": {"bar": "baz"}
}

proj_result1= jmespath.search(list_exp,source_5)
print(proj_result1) # ['James', 'Jacob', 'Jayden']


obj_exp ="reservations[*].instances[*].state"
source_6= {
  "reservations": [
    {
      "instances": [
        {"state": "running"},
        {"state": "stopped"}
      ]
    },
    {
      "instances": [
        {"state": "terminated"},
        {"state": "runnning"}
      ]
    }
  ]
}

proj_result2=jmespath.search(obj_exp,source_6)
print(proj_result2) #[['running', 'stopped'], ['terminated', 'runnning']]

# Flatten projections

source_7=[
  [0, 1],
  2,
  [3],
  4,
  [5, [6, 7]]
]
flat_exp ="[]"
flat_result = jmespath.search(flat_exp,source_7)
print(flat_result) # [0, 1, 2, 3, 4, 5, [6, 7]]

# filter

filter_exp="machines[?state=='running'].name"
filter_source ={
  "machines": [
    {"name": "a", "state": "running"},
    {"name": "b", "state": "stopped"},
    {"name": "b", "state": "running"}
  ]
}
filter_result = jmespath.search(filter_exp,filter_source)
print(filter_result)

# pipe expression

pipe_exp= "people[*].first | [0]"
pipe_source= {
  "people": [
    {"first": "James", "last": "d"},
    {"first": "Jacob", "last": "e"},
    {"first": "Jayden", "last": "f"},
    {"missing": "different"}
  ],
  "foo": {"bar": "baz"}
}

pipe_result = jmespath.search(pipe_exp,pipe_source)
print(pipe_result)  # James

# multiselect
multi_exp="people[].[first,last]"
multiselect_result = jmespath.search(multi_exp,pipe_source)
print(multiselect_result) # [['James', 'd'], ['Jacob', 'e'], ['Jayden', 'f'], [None, None]]

基本上把网站上例子试了一下,总体感觉功能是相当强大 (怀疑比 jsonpath 还要厉害一点).
从简单到复杂,都还是比较好用.

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 5 条回复 时间 点赞

看完了,恕我眼拙,说实话没发现比 jsonpath 好用的地方。。。1 对于 list 的操作 list 本身就能完成 2jsonpath 的用法建议也深入看看

果冻 回复

主要没找到 python 长期维护的 jsonpath 的包

请问下楼主,jsonpath 有不管前面的层级使用 $..就可以直接定位到某一层级,jemspath 支持吗?

同问楼上问题,找了很久没找到

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册