Easier access to values inside a Python dictionary
There may be times that you want to extract data from a dictionary based on a configuration that an end user supplies but you don't want them to have to supply the it in the bracketed format my_dict['field1']['field2']['field3']
but instead you want it to be field1.field2.field3
for easier reading.
Let's create a function that does just that! Assume the following dictionary:
{
"title": "This is my event",
"description": "This is a super awesome event.",
"venues": [
{
"name": "Lincoln Financial Field",
"address": "One Lincoln Financial Field Way",
"city": "Philadelphia",
"tags": ["Eagles"]
},
{
"name": "Wells Fargo Center",
"address": "3601 S Broad St.",
"city": "Philadelphia",
"tags": ["Flyers","Sixers","Concerts"]
},
{
"name": "Prudential Center",
"address": "25 Lafayette St",
"city": "Newark",
"tags": ["Devils","Bad Teams"]
}
],
"ticket_price": 50.00,
"status": "New",
}
The Python Code
def get_nested_field(message: dict, field: str):
'''
Iterates over nested fields to get the final desired value
e.g signal.rule.name should return the value of name.
If a target field is a list of dictionaries, the final value in
each dictionary will be returned as a single list.
Paramters:
message (dict): A dictionary of values you want to iterate over
field (str): The field you want to extract from the message in dotted format
Return:
value: The extracted value, may be the response from this
function calling itself again
'''
if isinstance(field, str):
args = field.split('.')
else:
args = field
if args and message:
element = args[0]
if element:
if isinstance(message, list):
values = []
value = [m for m in message if m is not None]
if any(isinstance(i, list) for i in value):
for l in value:
if isinstance(l, list):
values += [v for v in l if v is not None]
else:
values += [v for v in value if not isinstance(v, list)]
value = values
else:
value = message.get(element)
if isinstance(value, list):
if len(value) > 0 and isinstance(value[0], dict):
value = [get_nested_field(item, args[1:]) for item in value]
return value if len(args) == 1 else get_nested_field(value, args[1:])
Now the user can supply you a field in the format like venues.name
and the get_nested_field
function will return all the names of the venues.
print("venues.name", get_nested_field(event, "venues.name"))
print("venues.tags", get_nested_field(event, "venues.tags"))
Should produce
venues.name ['Lincoln Financial Field', 'Wells Fargo Center', 'Prudential Center']
venues.tags ['Eagles', 'Flyers', 'Sixers', 'Concerts', 'Devils', 'Bad Teams']
That is all. I thought this was interesting so wanted to share.