如何用Jinja2递归循环以点表示法打印字典词典?

时间:2018-01-07 21:20:08

标签: dictionary recursion yaml jinja2

我有以下YAML数据结构示例:(数据和结构可能会发生变化)

settings:
  subset1:
    sub1: val1
    sub2: val2
    sub3: val3
  subset2: val1

我想用Jinja打印它:(订购并不重要)

subset1.sub2 = val2
subset1.sub3 = val3
subset1.sub1 = val1
subset2 = val1

这就是我所拥有的:

{% for key, value in settings.items() recursive %}
{{ key }}{% if value is mapping %}.{{ loop(value.items()) }}{% else %} = {{ value }}
{% endif %}
{% endfor %}

但它给了我这个:

subset1.sub2 = val2
sub3 = val3
sub1 = val1
subset2 = val1

仅使用其所尊重的父元素打印第一个子元素。如何正确地与尊敬的父母一起打印所有子元素? (再次,订购并不重要)

谢谢!

1 个答案:

答案 0 :(得分:0)

这是我解决用例的方式:

from jinja2 import Template

settings = {
  'k1': {
    'k1': '1.1',
    'k2': {
        'k1': '1.2.1',
        'k2': {
            'k1': '1.2.2.1'
        },
        'k3': {
            'k1': {
                'k1': '1.2.3.1.1'
            },
        },
    },
  },
  'k2': {
    'k1': '2.1'
  },
  'k3': '3'
}

template = """
    {%- macro treedot(dict,string) %}
        {%- for key, value in dict.items() -%}
            {%- if value is mapping -%}
                {%- if string -%}
                    {%- set str = string ~ '.' ~ key  -%}
                {%- else -%}
                    {%- set str = key  -%}
                {%- endif -%}
                {{ treedot(value,str) }}
            {%- else -%}
                {%- if string %}
                    {{ string ~ '.' ~ key }} = {{ value }}
                {%- else %}
                    {{ key }} = {{ value }}
                {%- endif -%}
            {%- endif -%}
        {%- endfor -%}
    {%- endmacro -%}
    {{ treedot(settings,none) }}
"""
tpl = Template(template)
print tpl.render(settings=settings)

结果将是:

            k3 = 3
            k2.k1 = 2.1
            k1.k2.k3.k1.k1 = 1.2.3.1.1
            k1.k2.k2.k1 = 1.2.2.1
            k1.k2.k1 = 1.2.1
            k1.k1 = 1.1

使用宏比使用关键字“递归”更好,也允许递归,并允许将值的路径作为参数传递。 在此之前,我也尝试使用“递归”关键字,但由于每次迭代都会重置循环中的变量,因此无法满足我的需求。