Jinja2 and Json
Solution 1
The documentation reads:
It is possible to use loops recursively. This is useful if you are dealing with recursive data such as sitemaps. To use loops recursively you basically have to add the recursive modifier to the loop definition and call the loop variable with the new iterable where you want to recurse.
In your case this would be accomplished with the following:
<ul>
{% for key, value in linksList.items() recursive %}
<li>
{% if value is string %}
<a href="{{ value }}">{{ key }}</a>
{% else %}
{{ key }}
<ul>{{ loop(value.items()) }}</ul>
{% endif %}
</li>
{% endfor %}
</ul>
Solution 2
My 2 cents, just if someone comes here looking for rendering a JSON using Jinja, and complementing the response from @Ryon Sherman :)
- Since JSON may have int values as well as strings, you can use
if value is mapping
(and flip the if-condition) - If your output must feel like a JSON you can use
{{key|indent(width)}}
+loop.depth
- In my case, the template was for an email and
key|indent()
didn't work as expected so I ended up using an auxiliar{% for %}
loop:
<div>
<code>{
{% for key, value in dic.items() recursive %}
{% if value is mapping %}
<p>
{% for it in range(loop.depth) %} {% endfor %}{{key}}: {
</p>
{{ loop(value.items()) }}
<p>
{% for it in range(loop.depth) %} {% endfor %}}
</p>
{% else %}
<p>
{% for it in range(loop.depth) %} {% endfor %}{{key}}: {{value}},
</p>
{% endif %}
{% endfor %}
}</code>
</div>
lennykey
A software Engineer working with cloud technologies and a fan of Kotlin
Updated on July 10, 2022Comments
-
lennykey almost 2 years
I have for example a JSON File
{ "Google":{ "Web":"www.web.de", "Apps":{ "Drive": "DriveLink", "Dropbox": "DropboxLink" }, "Google Main":"http://mail.google.com", "G+":"http://plus.google.com" }, "Social":{ "Facebook":"http://www.facebook.de", "G+":"https://plus.google.com", "Xing":"http://www.xing.de", "LinkedIn":"http://www.linkedin.com", "Tumblr":"http://www.tumblr.com" }, "Fun":{ "Reddit":"http://www.reddit.com" } }
As you can see I have under the section Google a Nested Section named Apps
With CherryPy I hand over this JSON Object as following with the name linksList:
@cherrypy.expose def index(self): linksFile = open('links.json', 'r') linksList = json.load(linksFile) template = jinjaEnv.get_template('index.html') return template.render(linksList=linksList)
What I want is to render following:
- Google
- Web (as a link)
- Google Main
- G+
- Apps
- Drive
- Dropbox
- Social
- G+
and so on
What I don't understand is to do is to render this nested Objects like "Apps" recursively
- Google
-
lennykey over 11 yearsHey Ryon, thank you very much. That was exactly what I was searching for. What exactly helped was to test for a string. I tried for a dict a got an TemplateAssertionError: no test named 'dict'. Why is it that you cannot test for a dict or a list
-
Ryon Sherman over 11 years@lennykey It looks like Jinja doesn't provide a built-in test for dict or list though it is possible to create your own.