Astrea Astrea - 3 months ago 9
Python Question

How do I create a new dict of dicts from a dict with nested dicts in Python

I am starting with a dict received from an api

start_dict = {
"a": 795,
"b": 1337,
"c": [
{
"d1": 2,
"d2": [
{
"e1": 4
}
]
}
]
}


I need to create a separate dict from that dict. That has each of the keys and value separated by their key and value into there own dict. While keeping the nested dicts intact.

values =
{
"fields": [
{
"element_name": "a",
"value": 795
},
{
"element_name": "b",
"value": 1337
},
{
"element_name": "c",
"value": [
{
"element_name": "d1",
"value": 2
},
{
"element_name": "d2",
"value" : [
{
"element_name": "e1",
"value": 4
}
]
]
}
]
}


The actual dict is quite a bit larger but there are no more then one two deep nested dicts in the original but many single nested dicts. This is the only way the api will accept new data so I am kinda stuck until I figure it out. Any help is greatly appreciated as I am quite new to Python (3 Weeks) lol so if this is something simple please don't be to harsh.

Answer

You can build the output with a recursive function:

def transform(ob):
    if isinstance(ob, list):
        return [transform(v) for v in ob]
    elif not isinstance(ob, dict):
        return ob
    return [{'element_name': k, 'value': transform(v)}
            for k, v in ob.items()]

values = {'fields': transform(start_dict)}

so each key, value pair is transformed to a {'element_name': key, 'value': value} dictionary in a list, where any value that is itself a list or dictionary is transformed by a recursive call.

Demo:

>>> from pprint import pprint
>>> def transform(ob):
...     if isinstance(ob, list):
...         return [transform(v) for v in ob]
...     elif not isinstance(ob, dict):
...         return ob
...     return [{'element_name': k, 'value': transform(v)}
...             for k, v in ob.items()]
...
>>> start_dict = {
...     "a": 795,
...     "b": 1337,
...     "c": [
...         {
...             "d1": 2,
...             "d2": [
...                  {
...                       "e1": 4
...                  }
...         ]
...         }
...     ]
...     }
>>> pprint({'fields': transform(start_dict)})
{'fields': [{'element_name': 'a', 'value': 795},
            {'element_name': 'c',
             'value': [[{'element_name': 'd1', 'value': 2},
                        {'element_name': 'd2',
                         'value': [[{'element_name': 'e1', 'value': 4}]]}]]},
            {'element_name': 'b', 'value': 1337}]}