How to convert a inconsistent dictionary to .ini dynamically using python?

406 Views Asked by At

I have a use case where I ll be getting complex dictionaries as inputs in a inconsistent hirarchy. one use case would be like below :

pro : 1
rel : 1.2
del : demo
cb :{
 a : b
}
cd : {
 en : {
  b : a
}
}
cc : {
a : b
}

I used something like this : -

def jsonToDict(data):
    d = data
    res = defaultdict(dict)

    def dict2ini(d, root):
        for k, v in d.items():
            if isinstance(v, dict):
                _key = '%s.%s' % (root, k) if root else k
                if v:
                    dict2ini(v, _key)
                else:
                    res[_key] = {}
            elif isinstance(v, (str,int, float)):
                res[root] = {k:v}
    dict2ini(d, '')

    config = configparser.RawConfigParser()
    for key in sorted(res.keys()):
        config.add_section(key)
        for subKey, value in res[key].items():
            config.set(key, subKey, value)

    with open('example.ini', 'w') as configfile:
        config.write(configfile)

but the above doesn't process all the values present in my dict but only the first line in each section. I went through [ConfigParser][1]. But I am unable to find a solution to my use case can someone suggest me some workaround this also please note the above data is not fixed it will be changing according to our needs.

EXAMPLE INI :

pro = 1
rel = 1.2
del = demo

[cb]
a=b

[cd.en]
b=a
## suppose if multiple data is present in cd then 
[cd]
b=a
[cd.en]
b=a
## end

[cc]
a=b
1

There are 1 best solutions below

0
On BEST ANSWER

First, take a close look at your code. In dict2ini you iterate over a list of items in d:

    for k, v in d.items():

And if v is a scalar value, you add it to the res dictionary...but you always use the same key:

        elif isinstance(v, (str, int, float)):
            res[root] = {k: v}

So for each item in the dictionary, you're going to override the previous value of res[root]. With a few minor changes, I think you'll get closer to what you want:

def dict2ini(d, root):
    section = res[root]
    for k, v in d.items():
        if isinstance(v, dict):
            _key = '%s.%s' % (root, k) if root else k
            if v:
                dict2ini(v, _key)
            else:
                section[_key] = {}
        elif isinstance(v, (str,int, float)):
            section[k] = v
dict2ini(d, '')

This gives me as output:

[DEFAULT]
pro = 1
del = demo
rel = 1.2

[]

[cb]
a = b

[cc]
a = b

[cd]

[cd.en]
b = a

You obviously have a few additional things to fix there, but hopefully that sets you in the right direction.