Reputation: 387
I'm looking for a generic way to convert a flat dict like this:
{
"det_0_prod_di_0_field" : "value",
"det_0_prod_di_0_adi_0_field" : "value",
"det_0_prod_di_0_adi_1_field" : "value",
"det_1_prod_di_0_field" : "value",
"det_1_prod_di_0_adi_0_field" : "value",
"det_1_prod_di_0_adi_1_field" : "value",
}
Into this:
[
{
"det" : {
"prod" : [{
"di" : {
"field" : "value",
"adi" : [{"field" : "value"}, {"field" : "value"}]
},
}]
},
"det" : {
"prod" : [{
"di" : {
"field" : "value",
"adi" : [{"field" : "value"}, {"field" : "value"}]
},
}]
}
}
]
Notice that I have to create lists of dict for items that "repeat"... Also, It needs to be generic, because it can have many "levels of nesting"... every time "_0", "_1" etc appears in a key, a list should be created...
Thanks!
Upvotes: 0
Views: 749
Reputation: 6395
You might consider following and using then formencode's approach of serializing structures to flat names and then reading them back in.
http://www.formencode.org/en/latest/modules/variabledecode.html#module-formencode.variabledecode
Upvotes: 1
Reputation: 365707
The first step is obviously to split each key into components:
target = {}
for key, value in source.items():
components = key.split('_')
Now, what do you do with those components? Walk each one from left to right, keeping track of the current collection and the index or key to the next one, creating any missing sub-collections along the way.
You haven't specified your rule for what counts as an index vs. a key, what happens if indices are skipped or appear out of order, what happens if you get both an index and a key under the same prefix, etc., so I'll just pick some arbitrary rules for each—just treat every component as a key, because that makes for the shortest code. That's obviously not the rule you want, but if you understand the code, you should be able to adapt it as appropriate; if not, you need to understand it before you try to use it.
subtarget = target
for component in components[:-1]:
subtarget = subtarget.setdefault(component, dict())
subtarget[components[-1]] = value
If you understand the code but don't know how to adapt it, you probably have to look up the int
function, the try
statement, or the list.insert
method.
Upvotes: 2