使用 Ansible 将嵌套字典展平为 key/value 对

Flatten nested dictionary to key/value pairs with Ansible

---
- hosts: localhost
  vars:
    mydict:
      key1: val1
      key2: val2
      key3:
        subkey1: subval1
        subkey2: subval2
  tasks:
    - debug:
        msg: "{{ TODO }}"

如何使上述调试消息打印出嵌套字典中的所有 key/value 对?假设深度未知。我希望输出类似于:

{
  "key1": "val1",
  "key2": "val2",
  "subkey1": "subval1"
  "subkey2": "subval2"
}

写一个filter plugin and use pandas.json_normalize,例如

shell> cat filter_plugins/dict_normalize.py 
from pandas.io.json import json_normalize

def dict_normalize(d):
    df = json_normalize(d)
    l = [df.columns.values.tolist()] + df.values.tolist()
    return(l)

class FilterModule(object):
    def filters(self):
        return {
            'dict_normalize': dict_normalize,
        }

过滤器returns键和值列表

    - set_fact:
        mlist: "{{ mydict|dict_normalize }}"

给予

  mlist:
  - - key1
    - key2
    - key3.subkey1
    - key3.subkey2
  - - val1
    - val2
    - subval1
    - subval2

创建字典,例如

    - debug:
        msg: "{{ dict(mlist.0|zip(mlist.1)) }}"

给予

  msg:
    key1: val1
    key2: val2
    key3.subkey1: subval1
    key3.subkey2: subval2

如果子键是唯一的,删除路径

    - debug:
        msg: "{{ dict(_keys|zip(mlist.1)) }}"
      vars:
        _regex: '^(.*)\.(.*)$'
        _replace: ''
        _keys: "{{ mlist.0|map('regex_replace', _regex, _replace)|list }}"

给予

  msg:
    key1: val1
    key2: val2
    subkey1: subval1
    subkey2: subval2

备注

  • 安装软件包,例如python3-pandas

  • 过滤器可能会扩展以支持 json_normalize

    的所有参数
  • 贪婪正则表达式也适用于嵌套字典


问:"转key3.subkey1得到原始字典"

答:使用json_query。例如,给定第一步创建的字典

    - set_fact:
        mydict_flat: "{{ dict(mlist.0|zip(mlist.1)) }}"
  mydict_flat:
    key1: val1
    key2: val2
    key3.subkey1: subval1
    key3.subkey2: subval2

迭代键并从 mydict

中检索值
    - debug:
        msg: "{{ mydict|json_query(item) }}"
      loop: "{{ mydict_flat|list }}"

给予

  msg: val1
  msg: val2
  msg: subval1
  msg: subval2