Convert list of objects (string, string) into Dictionary (string, list<string>) in Ansible

删除回忆录丶 提交于 2019-12-24 10:02:17

问题


I have a list of objects (each object contains two attributes of type string) which I need to convert into Dictionary. The first attribute of the object will become a key, the second attribute of the object would have to be combined into a list of strings.

I went through several solutions but couldn't find exactly what I need.

Input Example:

[
    {
        "name": "AAA",
        "value": "111"
    },
    {
        "name": "AAA",
        "value": "222"
    },
    {
        "name": "BBB",
        "value": "333"
    },
    {
        "name": "BBB",
        "value": "444"
    },
    {
        "name": "CCC",
        "value": "555"
    }
]

Desired Outputs (either one works):

[
    {
        "name": "AAA",
        "value": [ "111", "222" ]
    },
    {
        "name": "BBB",
        "value": [ "333", "444" ]
    },
    {
        "name": "CCC",
        "value": [ "555" ]
    }
]
[
    "AAA": [ "111", "222" ],
    "BBB": [ "333", "444" ],
    "CCC": [ "555" ]
]

回答1:


The tasks below

- set_fact:
    my_list: "{{ my_list|default([]) +
                 [{item.0: item.1|json_query('[].value')}] }}"
  loop: "{{ input|groupby('name') }}"
- debug:
    var: my_list

give

"my_list": [
    {
        "AAA": [
            "111", 
            "222"
        ]
    }, 
    {
        "BBB": [
            "333", 
            "444"
        ]
    }, 
    {
        "CCC": [
            "555"
        ]
    }
]



回答2:


This is how I would approach the problem. The solution is mainly based on the use of the json_query filter

First, you need a list of all unique names in the list of objects so you can loop over it and extract the corresponding values. This is done by filtering the input variable with the following jinja2 template expresion {{ input | json_query("[].name") | unique }}

Now we just have to loop over that list and filter the input variable again. This time we want to extract a flat list of all values for all objects having the given name. This is done with the following example jinja2 expression: {{ input | json_query("[?name=='a_unique_name'].value") }}

The rest is just a matter of setting facts correctly, either in a new list or hashmap as your requested. I made both in the following example playbook.

Note: I used yaml folded blocks with white space control (>-) in this example to ease writing (limiting quotes escaping...) and reading (long lines split...). If you are not familiar with them you can check https://yaml-multiline.info/ for a complete overview of all options.

The playbook

---
- name: Rearrange var example
  hosts: localhost
  gather_facts: false

  vars:

     input: [
      { "name": "AAA", "value": "111" },
      { "name": "AAA", "value": "222" },
      { "name": "BBB", "value": "333" },
      { "name": "BBB", "value": "444" },
      { "name": "CCC", "value": "555" }
     ]

  tasks:

    - name: Create list and dict vars
      vars:
        jsquery: >-
          [?name=='{{ item }}'].value
      set_fact:
        list_var: >-
          {{
            list_var | default([])
            +
            [{'name': item, 'value': input | json_query(jsquery)}]
          }}
        dict_var: >-
          {{
            dict_var | default({})
            | combine ({ item: input | json_query(jsquery)})
          }}
      loop: "{{ input | json_query('[].name') | unique }}"


    - name: Show calculated list and dict vars
      debug:
        var: "{{ item }}"
      loop:
        - list_var
        - dict_var

Which gives:

PLAY [Rearrange var example]  ************************************************

TASK [Create list and dict vars] *********************************************
ok: [localhost] => (item=AAA)
ok: [localhost] => (item=BBB)
ok: [localhost] => (item=CCC)

TASK [Show calculated vars] **************************************************
ok: [localhost] => (item=list_var) => {
    "ansible_loop_var": "item",
    "item": "list_var",
    "list_var": [
        {
            "name": "AAA",
            "value": [
                "111",
                "222"
            ]
        },
        {
            "name": "BBB",
            "value": [
                "333",
                "444"
            ]
        },
        {
            "name": "CCC",
            "value": [
                "555"
            ]
        }
    ]
}
ok: [localhost] => (item=dict_var) => {
    "ansible_loop_var": "item",
    "dict_var": {
        "AAA": [
            "111",
            "222"
        ],
        "BBB": [
            "333",
            "444"
        ],
        "CCC": [
            "555"
        ]
    },
    "item": "dict_var"
}

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




来源:https://stackoverflow.com/questions/56755332/convert-list-of-objects-string-string-into-dictionary-string-liststring

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!