sorin
sorin

Reputation: 170310

How to transform a nested dictionary into a list using json_query?

I do have a nested dictionary that looks like:

mydict:
  system:  # <-- group
    disk:  # <-- command name
      cmd: df -a
    memory:
      cmd: free
  hw:
    pci:
      cmd: lspci
      foo: bar

I would like to transform it into a list of dictionaries while saving the first two level keys as keys, as below:

mylist:
- cmd: "df -a"
  group: system
  name: disk
- cmd: "free"
  group: system
  name: memory
- cmd: "lspci"
  name: pci
  group: hw
  foo: bar

While I want to use is using json_query() ansible filter, I guess that the question is generic for json-path use.

Upvotes: 2

Views: 877

Answers (1)

Vladimir Botka
Vladimir Botka

Reputation: 67984

Given the nested dictionary

    nested_dict:
      system:
        disk:
          cmd: df -a
        memory:
          cmd: free
      hw:
        pci:
          cmd: lspci
          foo: bar

The file with the included tasks

shell> cat item-to-list.yml
- set_fact:
    mylist: "{{ mylist +
                [{'group': outer_item.key, 'name': item.key}|
                 combine(item.value)] }}"
  loop: "{{ outer_item.value|dict2items }}"

and the tasks below

    - set_fact:
        mylist: []
    - include_tasks: item-to-list.yml
      loop: "{{ nested_dict|dict2items }}"
      loop_control:
        loop_var: outer_item
    - debug:
        var: mylist

give

    "mylist": [
        {
            "cmd": "df -a", 
            "group": "system", 
            "name": "disk"
        }, 
        {
            "cmd": "free", 
            "group": "system", 
            "name": "memory"
        }, 
        {
            "cmd": "lspci", 
            "foo": "bar", 
            "group": "hw", 
            "name": "pci"
        }
    ]

Q: "How to transform a nested dictionary into a list using json_query?"

A: Neither in Ansible nor in JMESPath there is a method on how to combine requested dictionaries from the lists of "names" and "dictionaries_to_combine_with" (see below) except nested loops or custom filter plugins. json_query is a dead end here, I'm afraid.

    - debug:
        msg:
          - "group: {{ item.0 }}"
          - "names: {{ item.1 }}"
          - "dictionaries_to_combine_with {{ item.2 }}"
      with_together:
        - "{{ nested_dict.keys()|list }}"
        - "{{ nested_dict|json_query('*.[keys(@), values(@)]') }}"

Upvotes: 1

Related Questions