如何获取值在嵌套字典中的键

How to get keys which value is in nested dictionary

总结:

我像示例中那样嵌套了字典,我想遍历它。对于每个 "item" 我想要嵌套的键和值 f.e.

输入

python:
  lint:
    where: 'here'

输出:

python.lint.where: 'here'

为什么我需要它:

我正在创建通过 ansible 管理 visual studio 代码的角色。我想安装它,创建 settings.json(这个问题针对这种情况),install/remove 插件。配置应该从以下变量创建:扩展列表、设置字典、repo 路径等。有了这个角色,我可以为我的开发环境创建一个文件配置,我可以通过 'one-click'.

进行设置

有字典 configuration.yml:

## vscode config
code_config:
  python:
    pythonPath: '/usr/bin/python'
    linting:
      enabled: "true"
      pep8Enabled: "true"
      ignorePath:
        - '.code'
        - '.vscode'

和示例剧本

- hosts: localhost
  vars_files: 'configuration.yml'
  tasks:
    - name: Hello
      template:
        src: file.j2
        dest: /etc/file.conf

file.j2

{
{% for key,value in code_config %}
{{ key }}: {{ value }},
{% endfor %}
}

想要像这样的输出:

{
python.pythonPath: '/usr/bin/python',
python.linting.enabled: 'true',
python.linting.pep8Enabled: 'true',
}

使用标准 Ansible/Jinja2 过滤器很难实现这一点,但您可以创建自己的自定义过滤器。例如...

  1. 在您的 playbook 目录中创建一个名为 filter_plugins
  2. 的目录
  3. 创建 python 脚本 filter_plugins/dict2settings.py 内容如下:
#!/usr/bin/env python

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

def dict2settings(var, config={}, parent_keys=[]):
    if isinstance(var, dict):
        for key,value in var.items():
            parent_keys.append(key)
            dict2settings(value, config, parent_keys)
    else:
        config['.'.join(parent_keys)] = var
        parent_keys.pop()
    return config
  1. 在您的剧本中使用自定义过滤器:
- hosts: localhost
  gather_facts: no

  vars:
    code_config:
      python:
        pythonPath: '/usr/bin/python'
        linting:
          enabled: "true"
          pep8Enabled: "true"
          ignorePath:
            - '.code'
            - '.vscode'

  tasks:
    - copy:
        content: "{{ code_config | dict2settings | to_nice_json }}"
        dest: /etc/file.conf

输出文件将包含以下内容:

{
    "python.linting.enabled": "true",
    "python.linting.ignorePath": [
        ".code",
        ".vscode"
    ],
    "python.linting.pep8Enabled": "true",
    "python.pythonPath": "/usr/bin/python"
}

鉴于您在问题中的预期输出实际上无效 JSON,您可能需要使用模板或其他方式稍微调整格式。但是自定义过滤器只提供了一个平面 key/value 字典,所以它应该很容易使用。