转换列表中的字典

Convert dictionary in list

我有以下 json 文件

[
    {
        "v4-filter": {
            "accept_to_test1t": {
                "action": "accept"
            },
            "access_to_test2": [
                {
                    "source-prefix-list": "x.x.x.x/yy"
                },
                {
                    "destination-prefix-list": "x.x.x.x/yy"
                },
                {
                    "action": "accept"
                }
            ]
        }
    }
]

请注意,对于字典键 accept_to_test1 值又是一个字典 "action": "accept" 问题:我需要转换列表中的所有嵌套字典,如上面的案例。 在这种特定情况下,例如

accept_to_test1:[{“行动”:“接受”}]。 其余的都保持原样。 结果:

[
    {
        "v4-filter": {
            "accept_to_test1t": [
            {
                "action": "accept"
            }],
            "access_to_test2": [
            ... like before ...
        }
    }
]

我正在使用 jinja2 模板来呈现此数据,它有效但仅适用于字典列表。

{%- for d  in data_list -%}
    {%- for k,v  in d.items() -%} 
        {%- for term,value  in v.items() -%} 
        term {{ term  }} {{ '{ \n' }}
          {%- set label = namespace(source=false, dest=false, port=false, action=false, prot=false) -%}
          {%- for dict_item in value -%}
            {%- for key, value in dict_item.items()  -%}            
               {% if  key == "source-prefix-list" %}
               {% if not label.source %}  source-address::{% else %}{{ ' '*18 }}{% endif %} {{value}} {{ '\n' }}  
               {%- set label.source = true -%}
               {% endif %}
               {%- if  key == "destination-prefix-list" -%}
               {% if not label.dest %}  destination-address::{% else %}{{ ' '*20 }}{% endif %} {{value}} {{ '\n' }}  
               {%- set label.dest = true %} 
               {%- endif -%}
               {%- if  key == "destination-port" -%}
               {% if not label.port %}  destination-port::{% else %}{{ ' '*20 }}{% endif %} {{value}} {{ '\n' }}
               {%- set label.port = true -%}  
               {% endif %}
               {%- if  key == "action" -%}
               {% if not label.action %}  action::{% else %}{{ ' '*20 }}{% endif %} {{value}} {{ '\n' }}
               {%- set label.action = true -%}  
               {% endif %}
               {%- if  key == "protocol" -%}
               {% if not label.protocol %}  protocol::{% else %}{{ ' '*20 }}{% endif %} {{value}} {{ '\n' }}
               {%- set label.protocol = true -%}  
               {% endif %}
            {%- endfor -%}
          {%- endfor -%}
          {{ '} \n\n' }}
        {%- endfor -%}
    {%- endfor -%} 
{%- endfor -%} 
{# above template is for json file #}

渲染时出现问题

    {%- for key, value in dict_item.items()  -%}            
  jinja2.exceptions.UndefinedError: 'str object' has no attribute 'item

由于 {'action': 'accept'} 这不是一个可迭代的项目。 它适用于 [{'action': 'accept'}].

欢迎任何提示。

谢谢。

此问题的一个简单解决方案是检测 value 变量何时为字典,然后将其嵌入到列表中。对于检测,我们可以使用 mapping bultin 测试。 embedding是一个简单的封装:{%- set value_list = [value] %}.

{%- for d  in data_list -%}
    {%- for k,v  in d.items() -%}
        {%- for term,value  in v.items() -%}
        term {{ term  }} {{ '{ \n' }}
        {%- set label = namespace(source=false, dest=false, port=false, action=false, prot=false) -%}
        {%- if value is mapping() %}
            {%- set value_list = [value] %}
        {%- else %}
            {%- set value_list = value %}
        {%- endif %}
        {%- for dict_item in value_list -%}
            {%- for key, value in dict_item.items() -%}
            {%- if  key == "source-prefix-list" %}
            {%- if not label.source %}  source-address::{% else %}{{ ' '*18 }}{% endif %} {{value}} {{ '\n' }}
            {%- set label.source = true -%}
            {%- endif %}
            {%- if  key == "destination-prefix-list" -%}
            {%- if not label.dest %}  destination-address::{% else %}{{ ' '*20 }}{% endif %} {{value}} {{ '\n' }}
            {%- set label.dest = true %}
            {%- endif -%}
            {%- if  key == "destination-port" -%}
            {%- if not label.port %}  destination-port::{% else %}{{ ' '*20 }}{% endif %} {{value}} {{ '\n' }}
            {%- set label.port = true -%}
            {%- endif %}
            {%- if  key == "action" -%}
            {%- if not label.action %}  action::{% else %}{{ ' '*20 }}{% endif %} {{value}} {{ '\n' }}
            {%- set label.action = true -%}
            {%- endif %}
            {%- if  key == "protocol" -%}
            {%- if not label.protocol %}  protocol::{% else %}{{ ' '*20 }}{% endif %} {{value}} {{ '\n' }}
            {%- set label.protocol = true -%}
            {%- endif %}
            {%- endfor -%}
        {%- endfor -%}
        {{ '} \n\n' }}
        {%- endfor -%}
    {%- endfor -%}
{%- endfor -%}

输出:

term accept_to_test1t { 
  action:: accept 
} 

term access_to_test2 { 
  source-address:: x.x.x.x/yy 
  destination-address:: x.x.x.x/yy 
  action:: accept 
} 

我还修复了一些缩进问题。