Json JMESPath从对象的对象生成对象数组

Json JMESPath从对象的对象生成对象数组,json,ansible,jinja2,jq,jmespath,Json,Ansible,Jinja2,Jq,Jmespath,我有以下示例json文档(对象的对象): 我试着把它重塑成一组像 [ { "key1": { "key1a": [{"key1aa": "value1aa"}, {"key1ab": "value1ab"}],... }}, { "key2": { "key2a": [{"key2aa": "value2aa"}, {"key2ab": "value2ab"}],... }}, ... ] 我可以使用Ansible的jinja2过滤器json_查询中的JMESPath 这怎么可能

我有以下示例json文档(对象的对象):

我试着把它重塑成一组像

[
  { "key1": { "key1a": [{"key1aa": "value1aa"}, {"key1ab": "value1ab"}],... }},
  { "key2": { "key2a": [{"key2aa": "value2aa"}, {"key2ab": "value2ab"}],... }},
  ...
]
我可以使用Ansible的jinja2过滤器json_查询中的JMESPath

这怎么可能

谢谢

大卫

鉴于我对这出戏的看法

给予

使用
yaml
回调(
export-ANSIBLE\u STDOUT\u callback=yaml
)打印输出。然后在列表的第一项之后手动拆分输出


json\u查询

也可以使用
jmespath
创建列表,即
json\u查询
。例如,下面的任务给出了相同的结果

- set_fact:
    my_list: "{{ my_dict|
                 dict2items|
                 json_query('[].[{key: key, value: value}]')|
                 map('items2dict')|
                 list }}"
- set_fact:
    my_list: "{{ my_dict|dict2list }}"

到_nice_yaml

当使用过滤器
打印到\u nice\u yaml
时,更容易看到数据的结构。比如说

- debug:
    msg: "{{ my_list|to_nice_yaml }}"
给予


筛选插件

也可以使用自定义。比如插件

$ cat filter_plugins/dict_utils.py

def dict2list(d):
    l = []
    for i in d:
        h = {i:d[i]}
        l.append(h)
    return l

class FilterModule(object):

    def filters(self):
        return {
            'dict2list': dict2list
        }
下面的任务给出了相同的结果

- set_fact:
    my_list: "{{ my_dict|
                 dict2items|
                 json_query('[].[{key: key, value: value}]')|
                 map('items2dict')|
                 list }}"
- set_fact:
    my_list: "{{ my_dict|dict2list }}"

为方便起见:


请注意,两个示例中的数组都不是正确的JSON语法(数组元素应该位于对象内部)

因此,举个例子:

cat file
{
  "key1": { "key1a": [{"key1aa": "value1aa"}, {"key1ab": "value1ab"}] },
  "key2": { "key2a": [{"key2aa": "value2aa"}, {"key2ab": "value2ab"}] }
}
您可以使用
jq

<file jq 'to_entries|map({(.key):.value})'

仅使用jmespath(即json_查询)是不可能的,除非您已准备好松开顶级键。在这种情况下,只需将通配符jmespath表达式(即
*
)应用于对象

如果您不想松开顶级键,并且仍然希望将jmespath作为等式的一部分,那么下面的示例可以满足这些要求,但还需要一些过滤器

有关该场景的一些详细信息:

  • 将初始哈希转换为
    {key:XXX,value:YYY}
  • 使用
    json\u query
    将哈希列表(即
    [{},{}]
    )转换为哈希列表(即
    [{}],{}]
  • 在结果列表的每个元素上映射
  • 最后,将临时对象从
    map
    转换为可用列表
其中:


PLAY [Transform hash to list with jmespath and dict2items/items2dict] ***************************************************************************************************************************************************************************************************

TASK [Do transform with json_query] *************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        {
            "key1": {
                "key1a": [
                    {
                        "key1aa": "value1aa"
                    },
                    {
                        "key1ab": "value1ab"
                    }
                ]
            }
        },
        {
            "key2": {
                "key2a": [
                    {
                        "key2aa": "value2aa"
                    },
                    {
                        "key2ab": "value2ab"
                    }
                ]
            }
        }
    ]
}

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

请注意,它肯定不是一个正确的json语法,但仍然是有效的yaml,导致的数据结构与您在答案中修复的数据结构完全相同。(基于jq)可以毫无疑问地解释它是的,你说得对。我的问题。此处我的JSON不是有效的JSON语法。我纠正了它。我试图阻止ansible中的jq,因为它有额外的依赖关系。我的json对象是通过Ansible的uri模块从弹性角色API响应的。他们没有回应。我不知道他们为什么在SpacesAPI中这样做,而不是在角色API中这样做。谢谢你的回答。但是那样的话,我会松开键'key1','key2','keyX',它们都很重要。很好,我跑得有点快。同时,我感到震惊的是,这使得jmespath根本不可行。这对jmespath是不可行的。。。。单独地请看我更新的答案,它仍然是等式的一部分(但使用了更多的过滤器)。
<file jq 'to_entries|map({(.key):.value})'
---
- name: Transform hash to list with jmespath and dict2items/items2dict
  hosts: localhost
  gather_facts: false

  vars:
    my_object: {
      "key1": { "key1a": ["key1aa": "value1aa", "key1ab": "value1ab"] },
      "key2": { "key2a": ["key2aa": "value2aa", "key2ab": "value2ab"] }
    }

  tasks:
    - name: Do transform with json_query
      debug:
        msg: >-
          {{
            my_object
            | dict2items
            | json_query('[].[{key: key, value: value}]')
            | map('items2dict')
            | list
          }}

PLAY [Transform hash to list with jmespath and dict2items/items2dict] ***************************************************************************************************************************************************************************************************

TASK [Do transform with json_query] *************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        {
            "key1": {
                "key1a": [
                    {
                        "key1aa": "value1aa"
                    },
                    {
                        "key1ab": "value1ab"
                    }
                ]
            }
        },
        {
            "key2": {
                "key2a": [
                    {
                        "key2aa": "value2aa"
                    },
                    {
                        "key2ab": "value2ab"
                    }
                ]
            }
        }
    ]
}

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