3

I'm trying to use jinja2 to output a nested dictionary to a yaml file. However I'm not sure how to access the nested dicts. With a flat dict for data I can use the below.

 - request:
        path: {{ path }}
        headers:
          origin: 'somedomain.com'
          user-agent: 'agent'
          referer: 'some.domain.com'
          authority: 'somedomain.com'
        data:
          {% for key, value in data.items() -%}
          {{ key }}: '{{ value }}'
          {%- endfor %}
      response:
        content:
          file: {{ content }}

However with a nested dict like below how do I achieve the output at the bottom?

{'toplevelkey1': {'nestedkey1': 'value1', 'nestedkey2': 123, 'nestedkey3': '55',
                 'nestedkey4': 1560}, 'toplevelkey34': 'df',
 'toplevelkey2': {'somekey12': 68, 'somekey58': False, 'somekey48': 3, 'somekey38': 'ADF',
                              'somekey39': 'St'}, 'toplevel34': 'T',
 'toplevel8': {'key33': 68, 'key94': 3, 'key83': 'T', 'key84': 'dog'}}

Required output

   - request:
    path: /some/path
    headers:
      origin: 'somedomain.com'
      user-agent: 'agent'
      referer: 'somedomain.com'
      authority: 'somedomain.com'
    data:
      toplevelkey1: 
        nestedkey1: 'value1'
        nestedkey2: '123
        ....      : ....
      toplevel34: 'T'
      toplevelkey2:
        'somekey12': 68
         .....     :  .....
  response:
    content:
      file: address.json
Yunti
  • 6,761
  • 12
  • 61
  • 106

2 Answers2

5

I would introduce a custom recursive "pretty-print" filter that would support any level of nestedness:

def pretty(d, indent=10, result=""):
    for key, value in d.iteritems():
        result += " " * indent + str(key)
        if isinstance(value, dict):
            result = pretty(value, indent + 2, result + "\n")
        else:
            result += ": " + str(value) + "\n"
    return result

env.filters['pretty'] = pretty

And use it in the template as:

{{ data|pretty }}
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
  • That's cool, but where is the pretty filter to be defined exactly? And where's `env` coming from? – Serg Nov 18 '18 at 03:06
  • `pretty` is a function that you define somewhere visible to the code that instantiates the jinja environment. `env` is the Environment object, e.g. `env = jinja2.Environment(loader=jinja2.FileSystemLoader(''))` – Marcello Romani Jan 03 '20 at 14:16
2

There is a somewhat smaller and more general solution:

# License: public-domain
import yaml # This is pyyaml

def yaml_pretty(d, indent=10):
    dump = yaml.dump(d)
    res = ""
    for line in dump.split("\n"):
        res += " " * indent + line + "\n"
    return res

This handles all types, e.g. also (nested) lists.

Andreas Florath
  • 4,418
  • 22
  • 32