Get specific list of dict from json content using Ansible

Viewed 127

I spend a lot of times to finally didn't get what I need, my request is so complicated then I prefer share with you my concern::

I have this json.content to pars it:


        "json": {
            "content": [
                {
                    "name": "machine1",
                    "hasChildren": false,
                    "resourceData": {
                        "entries": [
                            {
                                "value": {
                                    "type": "string",
                                    "value": "Red Hat Enterprise Linux 7 (64-bit)"
                                },
                                "key": "MachineGuestOperatingSystem"
                            },
                            {
                                "value": {
                                    "type": "string",
                                    "value": "Folder1"
                                },
                                "key": "VMware.VirtualCenter.Folder"
                            },
                            {
                                "value": {
                                    "type": "boolean",
                                    "value": true
                                },
                                "key": "Destroy"
                            }
                        ]
                    }
                },
                {

                    "name": "machine2",
                    "hasChildren": false,
                    "resourceData": {
                        "entries": [
                            {
                                "value": {
                                    "type": "string",
                                    "value": "Red Hat Enterprise Linux 7 (64-bit)"
                                },
                                "key": "MachineGuestOperatingSystem"
                            },
                            {
                                "value": {
                                    "type": "string",
                                    "value": "Folder2"
                                },
                                "key": "VMware.VirtualCenter.Folder"
                            },
                            {
                                "value": {
                                    "type": "boolean",
                                    "value": false
                                },
                                "key": "Destroy"
                            }
                        ]
                    }
                },
                {
                    "name": "machine3",
                    "hasChildren": false,
                    "resourceData": {
                        "entries": [
                            {
                                "value": {
                                    "type": "string",
                                    "value": "Windows Server 2016 or later (64-bit)"
                                },
                                "key": "MachineGuestOperatingSystem"
                            },
                            {
                                "value": {
                                    "type": "string",
                                    "value": "Folder3"
                                },
                                "key": "VMware.VirtualCenter.Folder"
                            },
                            {
                                "value": {
                                    "type": "boolean",
                                    "value": true
                                },
                                "key": "Destroy"
                            }
                        ]
                    }
                }
            ]
        }


and I'd like to have as output Something like:

[{"name":"machine1", "OsName": "Red Hat Enterprise Linux 7 (64-bit)", "Folder": "Folder1"}, {"name":"machine2", "OsName": "Red Hat Enterprise Linux 7 (64-bit)", "Folder": "Folder2"},
{"name":"machine3", "OsName": "Windows Server 2016 or later (64-bit)", "Folder": "Folder3"}]

I tried all the solutions but no way, all result not what I want to expect. someone can help me to find a solution to get this attended result

1 Answers

The task below does the job

    - set_fact:
        _list: "{{ json.content|json_query(query) }}"
      vars:
        query: "[].{name: name,
                    OsName: resourceData.entries[0].value.value,
                    Folder: resourceData.entries[1].value.value}"

gives

  _list:
  - Folder: Folder1
    OsName: Red Hat Enterprise Linux 7 (64-bit)
    name: machine1
  - Folder: Folder2
    OsName: Red Hat Enterprise Linux 7 (64-bit)
    name: machine2
  - Folder: Folder3
    OsName: Windows Server 2016 or later (64-bit)
    name: machine

Q: "It changes the order of (key, value), so referencing by [0] or [1] will be not the same."

A: Select the items by the keys. You'll have to pipe the results and select the first items of the selected lists, e.g. the task below gives the same results

    - set_fact:
        _list: "{{ json.content|json_query(query) }}"
      vars:
        query: "[].{name: name,
                    OsName: resourceData.entries[?key==`MachineGuestOperatingSystem`].value.value|[0],
                    Folder: resourceData.entries[?key==`VMware.VirtualCenter.Folder`].value.value|[0]}"

Q: "Filter 'Red Hat ...' Get output"

  - Folder: Folder1
    OsName: Red Hat Enterprise Linux 7 (64-bit)
    name: machine1
  - Folder: Folder2
    OsName: Red Hat Enterprise Linux 7 (64-bit)
    name: machine2

A: Use selectattr, e.g. the task below does the job

    - debug:
        msg: "{{ _list|
                 selectattr('OsName', 'eq', 'Red Hat Enterprise Linux 7 (64-bit)')|
                 list }}"

Q: "Where I can learn this kind of search?"

A: There are examples in JMESPath Specification. As a hint, see the code below on how to translate these examples into Ansible json_query

Example1

    - name: 'search(foo, {"foo": "value"}) -> "value"'
      debug:
        msg: "{{ _dict|json_query(_query) }}"
      vars:
        _dict: {"foo": "value"}
        _query: "foo"

Example2

    - name: 'search(foo[?bar==`10`], {"foo": [{"bar": 1}, {"bar": 10}]}) -> [{"bar": 10}]'
      debug:
        msg: "{{ _dict|json_query(_query) }}"
      vars:
        _dict: {"foo": [{"bar": 1}, {"bar": 10}]}
        _query: "foo[?bar==`10`]"

Example3

    - name: 'search(foo | bar, {"foo": {"bar": "baz"}}) -> "baz"'
      debug:
        msg: "{{ _dict|json_query(_query) }}"
      vars:
        _dict: {"foo": {"bar": "baz"}}
        _query: "foo | bar"
Related