Reputation: 427
I am in need of a function used to convert the keys of a Python dict
to something else, according to a keys mapping. So for example let's say I have the mapping:
{
"olk_key_1": "new_key_1",
"olk_key_2": "new_key_2",
"olk_key_3": "new_key_3",
}
And the dict
:
{
"old_key_1": 1,
"old_key_2": 2,
"old_key_3": 3,
}
What I want is:
{
"new_key_1": 1,
"new_key_2": 2,
"new_key_3": 3,
}
The tricky part about this is that the functions MUST SUPPORT ANY SORT OF NESTED STRUCTURE.
That includes:
dict
s of dict
sdict
s of list
slist
s of dict
sI currently have an ugly working function. Anything better looking (feel free to just refactor my code) will be considered as an answer.
def map_keys(self, data, mapping):
"""
This function converts the data dictionary into another one with different keys, as specified by the mapping
parameter
:param data: The dictionary to be modified
:param mapping: The key mapping
:return: A new dictionary with different keys
"""
new_data = data.copy()
if isinstance(new_data, list):
new_data = {"tmp_key": new_data}
mapping.update({"tmp_key": "key_tmp"})
iterate = list(new_data.items())
for key, value in iterate:
if isinstance(value, list) and isinstance(value[0], dict):
new_list = []
for item in new_data[key]:
new_list.append(self.map_keys(item, mapping))
new_data[mapping[key]] = new_list
else:
new_data[mapping[key]] = value
new_data.pop(key)
if "key_tmp" in new_data:
new_data = new_data["key_tmp"]
return new_data
EDIT
As an example, the function should be able to convert inputs such as (intentionally excessively convoluted):
[
{
"a": 1,
"b":[
{
"c": 1,
"d": 1
},
{
"e": 1,
"f": 1
}
]
},
{
"g": {
"h": {
"i": 1,
},
"j": {
"k": 1
}
}
}
]
Upvotes: 2
Views: 1233
Reputation: 195438
You can use json.load()
with custom objects_pairs_hook
parameter (doc):
mapping_d = {
"old_key_1": "new_key_1",
"old_key_2": "new_key_2",
"old_key_3": "new_key_3",
}
d = {
"old_key_1": 1,
"old_key_2": 2,
"old_key_3": [
{"old_key_1": 4},
{"old_key_2": 5}
],
}
import json
def fn(obj):
rv = dict([(mapping_d.get(n, n), v) for n, v in obj])
return rv
d = json.loads(json.dumps(d), object_pairs_hook=fn)
from pprint import pprint
pprint(d, width=30)
Prints:
{'new_key_1': 1,
'new_key_2': 2,
'new_key_3': [{'new_key_1': 4},
{'new_key_2': 5}]}
Upvotes: 4