smriti
smriti

Reputation: 1203

iterate over nested objects in python

I have a python object that looks like this. I am trying to parse this object and turn it to a human readable string which I need to put in the logs. How can I recursively loop through this considering the object could be nested dictionaries or nested lists or dictionaries inside lists inside dictionaries etc.

{"plugins": 
  [
    {"Chrome PDF Viewer": "mhjfbmdgcfjbbpaeojofohoefgiehjai"}, 
    {"Chrome PDF Viewer": "internal-pdf-viewer"}, 
    {"Native Client": "internal-nacl-plugin"}, 
    {"Shockwave Flash": "PepperFlashPlayer.plugin"}, 
    {"Widevine Content Decryption Module": "widevinecdmadapter.plugin"}
  ]
}

I want to possibly serialize the above to look something like this

"plugins: 
     Chrome PDF Viewer": "mhjfbmdgcfjbbpaeojofohoefgiehjai, 
     Chrome PDF Viewer": "internal-pdf-viewer, 
     Native Client": "internal-nacl-plugin, 
     Shockwave Flash": "PepperFlashPlayer.plugin, 
     Widevine Content Decryption Module": "widevinecdmadapter.plugin"

My code so far [this works for nested dictionaries but I am not sure how I can alter this to support lists in the above object]:

result_str = ""

def dictionary_iterator(results):
    global result_str
    for key, value in results.items():
        if isinstance(value, dict):
            result_str = result_str + key + ": \n \t"
            dictionary_iterator(value)
        else:
            result_str = result_str + key + ": " + str(value) + "\n"

    return result_str

I have looked over possible answers but could not find a solution.

Upvotes: 2

Views: 2929

Answers (3)

Maurice Meyer
Maurice Meyer

Reputation: 18106

You need an elif-condition in case of type == list and a indentation tracker:

data = {"plugins": 
  [
    {"Chrome PDF Viewer": "mhjfbmdgcfjbbpaeojofohoefgiehjai"}, 
    {"Chrome PDF Viewer": "internal-pdf-viewer"}, 
    {"Native Client": "internal-nacl-plugin"}, 
    {"Shockwave Flash": "PepperFlashPlayer.plugin"}, 
    {"Widevine Content Decryption Module": "widevinecdmadapter.plugin"}
  ],
  "anotherLevel":
    {
        "sublevel": [
            {'item1': 'value1'}
        ]
    }
}

result_str = ""
def dictionary_iterator(indent, data):
    global result_str

    if isinstance(data, dict):
        for key, value in data.items():
            result_str += indent*'\t' + key + '\n'
            indent = indent + 1
            dictionary_iterator(indent, value)

    elif isinstance(data, list):
        for item in data:
            if isinstance(item, dict) and len(list(item.keys())) == 1:
                key = list(item.keys())[0]
                value = item[key]
                result_str += indent*'\t' + key + ': ' + value + '\n'
            else:
                indent = indent + 1
                dictionary_iterator(indent, item)
    return result_str


if __name__ == '__main__':
    print(dictionary_iterator(0, data))

That will print out:

plugins
    Chrome PDF Viewer: mhjfbmdgcfjbbpaeojofohoefgiehjai
    Chrome PDF Viewer: internal-pdf-viewer
    Native Client: internal-nacl-plugin
    Shockwave Flash: PepperFlashPlayer.plugin
    Widevine Content Decryption Module: widevinecdmadapter.plugin
    anotherLevel
        sublevel
            item1: value1

Upvotes: 1

Raunak Agarwal
Raunak Agarwal

Reputation: 7228

The formatting might be a bit off

def humanizer(input, result=''):
    if type(input) == dict:
        for k, v in input.items():
            if type(v) == str:
                result += '%s:%s\n\t' % (str(k), str(v))
            elif type(v) in (dict, list):
                result += '%s:\n\t' % str(k)
                result = humanizer(v, result)
                result += '\n\t'
    elif type(input) == list:
        for item in input:
            if type(item) == str:
                result += item
                continue
            result = humanizer(item, result) + '\n\t'
    else:
        result += input + '\n\t'
    return result

Result:

plugins:
        Chrome PDF Viewer:mhjfbmdgcfjbbpaeojofohoefgiehjai

        Chrome PDF Viewer:internal-pdf-viewer

        Native Client:internal-nacl-plugin

        Shockwave Flash:PepperFlashPlayer.plugin

        Widevine Content Decryption Module:widevinecdmadapter.plugin

Upvotes: 2

kristaps
kristaps

Reputation: 1723

Maybe the output of pformat would suit you:

from pprint import pformat
results_str = pformat(results)

Upvotes: 2

Related Questions