Jinja2 Recursive Rendering of a Deep Data Structure to YAML: Difference between revisions
Jump to navigation
Jump to search
(Created page with "=Internal= * Jinja2 =Overview= The method uses recursive macros.") |
|||
Line 2: | Line 2: | ||
* [[Jinja2#Recursive_Rendering_of_a_Deep_Data_Structure|Jinja2]] | * [[Jinja2#Recursive_Rendering_of_a_Deep_Data_Structure|Jinja2]] | ||
=Overview= | =Overview= | ||
The method uses recursive | The method uses a recursive [[Jinja2#Macros|macro]]. | ||
=The Template= | |||
<syntaxhighlight lang='jinja'> | |||
{%- macro recursively_render_data_structure(d, indentation_index) -%} | |||
{%- if d is number %}{{ d }} | |||
{%- elif d is string %}"{{ d }}" | |||
{%- elif d is mapping -%} | |||
{%- for key, value in d.items() %} | |||
{{ ' ' * indentation_index }}{{ key }}: {{ recursively_render_data_structure(value, indentation_index + 2) }} | |||
{%- endfor %} | |||
{%- elif d is iterable %} | |||
{%- for i in d %} | |||
{{ ' ' * indentation_index }} - {{ recursively_render_data_structure(i, indentation_index + 4) }} | |||
{%- endfor %} | |||
{%- else %}ERROR: UNKNOWN VALUE {{ d }} | |||
{%- endif %} | |||
{%- endmacro -%} | |||
{{- recursively_render_data_structure(m, 0) }} | |||
</syntaxhighlight> | |||
=The Rendering Code= | |||
The code includes a test that the rendered structure is equivalent with the input: | |||
<syntaxhighlight lang='py'> | |||
from pathlib import Path | |||
import yaml | |||
from jinja2 import Environment, FileSystemLoader | |||
tdir = Path('.') | |||
template = Environment(loader=FileSystemLoader(tdir)).get_template('experimental-jinja-template.yaml.j2') | |||
yaml_data = """ | |||
config: | |||
color: blue | |||
size: 1 | |||
samples: | |||
- name: venice | |||
neighborhoods: | |||
cannaregio: 1 | |||
castello: 2 | |||
giudecca: 3 | |||
- name: genoa | |||
neighborhoods: | |||
molo: 1 | |||
foce: 2 | |||
marassi: 3 | |||
- name: florence | |||
neighborhoods: | |||
santamaria: 1 | |||
sanmarco: 2 | |||
santacroce: 3 | |||
no-such-neighborhood: | |||
- a1: v1 | |||
a2: v2 | |||
- b | |||
- c | |||
""" | |||
m = yaml.safe_load(yaml_data) | |||
rendered_text = template.render(m=m) | |||
print(rendered_text) | |||
m2 = yaml.safe_load(rendered_text) | |||
assert m == m2 | |||
</syntaxhighlight> |
Revision as of 22:30, 23 August 2023
Internal
Overview
The method uses a recursive macro.
The Template
{%- macro recursively_render_data_structure(d, indentation_index) -%}
{%- if d is number %}{{ d }}
{%- elif d is string %}"{{ d }}"
{%- elif d is mapping -%}
{%- for key, value in d.items() %}
{{ ' ' * indentation_index }}{{ key }}: {{ recursively_render_data_structure(value, indentation_index + 2) }}
{%- endfor %}
{%- elif d is iterable %}
{%- for i in d %}
{{ ' ' * indentation_index }} - {{ recursively_render_data_structure(i, indentation_index + 4) }}
{%- endfor %}
{%- else %}ERROR: UNKNOWN VALUE {{ d }}
{%- endif %}
{%- endmacro -%}
{{- recursively_render_data_structure(m, 0) }}
The Rendering Code
The code includes a test that the rendered structure is equivalent with the input:
from pathlib import Path
import yaml
from jinja2 import Environment, FileSystemLoader
tdir = Path('.')
template = Environment(loader=FileSystemLoader(tdir)).get_template('experimental-jinja-template.yaml.j2')
yaml_data = """
config:
color: blue
size: 1
samples:
- name: venice
neighborhoods:
cannaregio: 1
castello: 2
giudecca: 3
- name: genoa
neighborhoods:
molo: 1
foce: 2
marassi: 3
- name: florence
neighborhoods:
santamaria: 1
sanmarco: 2
santacroce: 3
no-such-neighborhood:
- a1: v1
a2: v2
- b
- c
"""
m = yaml.safe_load(yaml_data)
rendered_text = template.render(m=m)
print(rendered_text)
m2 = yaml.safe_load(rendered_text)
assert m == m2