I want to replace keys name of a dictionary by passing a mapping dict with a function that replace also nested keys. The issue is that I have multiple keys named 'id' in nested dictionary and I want to rename these 'id' with specific names.
Initial dictionnary:
initial_dict = {'id': 1, 'netAmount': 10.2, 'modifiedOn': '2017-01-01',
'statusId': 3, 'approvalStateId': 3, 'approvalState': {'id': 3,'name':'Approved'}}
Mapping dict:
mapping_dict = {'id': 'pr_id', 'netAmount': 'net_amount', 'modifiedOn': 'modified_date',
'statusId': 'status_id', 'approvalStateId': 'approval_id','approvalState':{'id':'approv_id'}}
Desired output of the dictionary:
output_dict = {'pr_id': 1, 'net_amount': 10.2, 'modified_date': '2017-01-01',
'status_id': 3, 'approval_id': 3, 'approvalState': {'approv_id': 3, 'name': 'Approved'}}
What I did is this but it only replace keys of the first level of the dict and if I try to set nested keys in the mapping dict, I get an error.
def map_fields(obj):
new_obj = {}
mapping_dict = {'id': 'pr_id', 'netAmount': 'net_amount', 'modifiedOn': 'modified_date',
'statusId': 'status_id', 'approvalStateId': 'approval_id','approvalState':{'id':'approv_id'}}
for key in obj.keys():
if key in mapping_dict:
new_key = mapping_dict[key]
else:
new_key = key
new_obj[new_key] = obj[key]
return new_obj
Do you have any idea how to do it?
Thanks
You need a recursive function to be able to step up through the nested dictionaries. The key is that when recursing, you need to pass both the child dictionary, and the child mapping dictionary.
Note that the structure of your mapping dict is specific to this problem, and doesn't allow you to change the key of a nested dictionary - you'd need to restructure how you store the mapping to achieve that.
The following should do what you want (print statements added to help follow the logic when it runs):
Also if you want the same result but do not want to use a nested mapping dict such as :
(ie 'id'/'approv_id' is not nested in 'approvalState')
You can use the slightly different function:
This can be especially useful if the key 'approvalState' was also to map (to something like 'resultState', ie if your result needed to be:
In which case, you would just have had to add the key/value pair 'approvalState'/'resultState' in your mapping dict.