1

I just learned how to use multilevel defaultdict from here. Same subject has been discussed here. Unfortunately my project uses JSON to save the data, and when I load the data from JSON file, the defaultdict functionality is gone. I tried to search a solution, but couldn't find or understand any. So, how I should read n-level dict from JSON (or TOML) file and apply the defaultdict functionality to it?

So simple me scribbled a simplified example about the problem and a basic solution (for this spesific 3-level case) below. Do you have better / understandable / well explained solution to this?

Thanks mates!

from collections import defaultdict
from pprint import pprint
import json

class DeepDict(defaultdict):
    """Multilevel defaultdict functionality
    this snippet is from: https://stackoverflow.com/a/53671579"""
    def __call__(self):
        return DeepDict(self.default_factory)

group = 1
item = 12
item2 = 13
parts = ['asd','fgh']
parts2 = ['asf','fgj']

partlist = DeepDict(DeepDict(list))
partlist[group][item].extend(parts)
partlist[group][item2].extend(parts2)
pprint(partlist) #1 correct multilevel defaultdict
with open('data.json', 'w') as fp:
    json.dump(partlist, fp, indent=4)

with open('data.json', 'r') as fp:
    temp = json.load(fp)
pprint(temp) #2 plain dict

part_import = DeepDict(DeepDict(list))
part_import.update(temp)
pprint(part_import) #3 old data in plain dict

part_import = DeepDict(DeepDict(list))
#recreate and populate data to multilevel defaultdict
for k in temp:
    for l in temp[k]:
        part_import[k][l] = temp[k][l]
pprint(part_import) #4 correct multilevel defaultdict

produces to console:

DeepDict(DeepDict(<class 'list'>, {}),
         {1: DeepDict(<class 'list'>,
                      {12: ['asd', 'fgh'],
                       13: ['asf', 'fgj']})})
{'1': {'12': ['asd', 'fgh'], '13': ['asf', 'fgj']}}
DeepDict(DeepDict(<class 'list'>, {}),
         {'1': {'12': ['asd', 'fgh'], '13': ['asf', 'fgj']}})
DeepDict(DeepDict(<class 'list'>, {}),
         {'1': DeepDict(<class 'list'>,
                        {'12': ['asd', 'fgh'],
                         '13': ['asf', 'fgj']})})
Pena86
  • 66
  • 6
  • I just noticed, that the JSON dump - load changed the keys from int to str, but that isn't important here (it does explain some errors in the project tough). – Pena86 Oct 27 '20 at 14:15
  • Json keys are always strings. This isn't a json dump problem -- it's to do with the definition of json – Pranav Hosangadi Oct 27 '20 at 14:56
  • You could put the loading code in a classmethod of DeepDict for cleaner usage. e.g. `DeepDict.load(filename)`. But apart from that, it's the same you already have. – Wups Oct 27 '20 at 15:07

0 Answers0