Jinja2 — Отступ и рекурсивный цикл из списка

#json #ansible #jinja2

Вопрос:

Запрос в основном связан с Jinja2 для рекурсии по циклу и добавления элементов в рекурсивный формат типа JSON.

Например, получен список/данные, разделенные каналами, который представляет собой «иерархию, разделенную каналами», как показано ниже

     World|North_America|USA|Texas
    World|Europe|UK|England|London
    World|Australia
 

Иерархия может быть любого уровня, и я хотел иметь формат JSON, основанный на иерархии, используя шаблон Jinja2

То, что я пробовал, это

     {% for item in  pipe_separated_hierarchy.split('|') %}
    "obj_{{loop.index}}": {
        "{{item}}": {
            "my_description_obj{{loop.index}}",
            "obj_{{loop.index}}": {
            <<<loop from 2nd iteration again >>> # not sure how to loop.index amp; item ?
        }
    {% endfor %}
 

Я ищу выход

     "obj_1": {
      "World": {
        "obj_2": {
          "North_America": {
            "obj_3": {
              "USA": {
                "obj_4": "Texas"
                }
              }
            }
          }
        }
      }
 

Есть идеи, как пройтись по списку, сохраняя счетчик рядом и отступ?

Комментарии:

1. Вы пытаетесь создать недопустимый json здесь, поэтому мы, вероятно, сможем ответить на ваш вопрос, но он все равно будет недействительным, например { "World": { "my_description_obj4", "texas" } } , будет недействительным, потому my_description_obj4 что ни texas у кого нет ключа

2. извините, выше приведен пример, который я ввел в SO. но мыслительный процесс заключается в создании рекурсивного цикла. просто хотел изложить концепцию.

Ответ №1:

Например

 - hosts: localhost
  vars:
    l1:
      - World|North_America|USA|Texas
      - World|Europe|UK|England|London
      - World|Australia
  tasks:
    - debug:
        var: _out|from_yaml
      loop: "{{ l1 }}"
      vars:
        _list: "{{ item.split('|') }}"
        _len: "{{ _list|length }}"
        _out: |
          {% for i in range(_len|int) %}
          {{ 'obj_'|indent(width=(i*4),first=true) }}{{ i 1 }}:
            {{ _list[i]|indent(width=(i*4),first=true) }}{{ ":" if not loop.last else "" }}
          {% endfor %}
 

дает

 ok: [localhost] => (item=World|North_America|USA|Texas) => {
    "_out|from_yaml": {
        "obj_1": {
            "World": {
                "obj_2": {
                    "North_America": {
                        "obj_3": {
                            "USA": {
                                "obj_4": "Texas"
                            }
                        }
                    }
                }
            }
        }
    },
    "ansible_loop_var": "item",
    "item": "World|North_America|USA|Texas"
}
ok: [localhost] => (item=World|Europe|UK|England|London) => {
    "_out|from_yaml": {
        "obj_1": {
            "World": {
                "obj_2": {
                    "Europe": {
                        "obj_3": {
                            "UK": {
                                "obj_4": {
                                    "England": {
                                        "obj_5": "London"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "ansible_loop_var": "item",
    "item": "World|Europe|UK|England|London"
}
ok: [localhost] => (item=World|Australia) => {
    "_out|from_yaml": {
        "obj_1": {
            "World": {
                "obj_2": "Australia"
            }
        }
    },
    "ansible_loop_var": "item",
    "item": "World|Australia"
}