首页 > 解决方案 > 如何在 jmespath 中匹配数组名称本身的正则表达式(json 元素字符串正则表达式通配符)

问题描述

如何使用jmespath中的正则表达式在 json 中搜索数组?

考虑以下 JSON 文档(如果构造不佳,请放在一边):

{
  "people_in_town": [
    {"letter": "a"},
    {"letter": "b"},
  ],
  "people_with_shoes": [
    {"letter": "c"},
    {"letter": "d"},
  ],
  "people_with_town": [
    {"letter": "e"},
    {"letter": "f"},
  ],
}

现在,jmespath可以很容易地对列表的所有元素进行通配符,people_in_town[*].letter从而返回[a, b].

但我想使用的通配符是数组名称的正则表达式,如下所示:

people_*_town.letter

这样它将返回 and 的内容,people_in_town以及后面跟着. 的people_with_town任何数组。当然,上面的例子是行不通的。people_<some string>_town

如何使用 jmespath 将 json 文档中的数组与正则表达式匹配?

标签: arraysjsonregexwildcardjmespath

解决方案


只是涵盖您从链接问题中添加的用例,而不是关键问题中真正通用的通配符,这很可能是不可能的。

但万一你确实有什么要查询的

key in ['people_in_town', 'people_with_town']

因此,使用有限数量的已知密钥,您绝对可以执行类似的操作

[@.people_in_town, @.people_with_town][].letter

那将给出:

[
  "a",
  "b",
  "e",
  "f"
]

使用纯 JMESPath 方法您将面临的主要问题是,您可以对键执行的唯一操作是基于keys函数的,遗憾的是,不可能同时拥有两个键数组,然后返回要选择的部分那些钥匙。

如果您真的只想使用 JMESPath,那么您必须以两遍结束:

  1. keys使用starts_with/ends_with函数创建键列表
  2. 然后进行第二次传递以返回上述查询

从 Ansible 的角度来看,这最终得到了这个非常丑陋的剧本:

- hosts: all
  gather_facts: no

  tasks:
    - debug: 
        msg: >-
          {{
              data | json_query(
                "[@." ~ data | json_query(
                  "join(
                    ',@.', 
                    keys(@)[?
                      starts_with(@, 'people_') 
                      && ends_with(@, '_town')
                    ]
                  )"
                ) ~ "][].letter"
              )
          }}
      vars:
        data:
          people_in_town:
            - letter: a
            - letter: b
          people_with_shoes:
            - letter: c
            - letter: d
          people_with_town:
            - letter: e
            - letter: f

这会产生

PLAY [all] *******************************************************************************************

TASK [debug] *****************************************************************************************
ok: [localhost] => 
  msg:
  - a
  - b
  - e
  - f

PLAY RECAP *******************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

所以,如果我真的是你,我会坚持在链接问题的答案中提出的选项,并在这个特定用例中远离 JMESPath。


推荐阅读