How to index a json key array that sometimes only has one element, and is no longer an iterable?
Question:
I’m new to json, and I’m having trouble dealing with indexing keys that usually have sub-array but sometimes they don’t.
Usually, key2 and key3 contain sub-array:
json_obj = json.loads(x)
json_obj["key1"]["key2"][idx]["key3"][idx]["key4"]
However, sometimes key2 and/or key3 is no longer an array
executing above code would throw an exception
to retrieve key4:
json_obj["key1"]["key2"]["key3"][idx]["key4"]
json_obj["key1"]["key2"][idx]["key3"]["key4"]
json_obj["key1"]["key2"]["key3"]["key4"]
Is there an elegant way to retrieve key4 regardless the condition of key2 and key3?
Answers:
All you need to do is transverse the tree, getting the next key if the value is a dictionary or getting an index if the value is a list. Here is a function to do that general behavior:
def getKey(data, path, indices):
el = data
# keep transversing until we find a primitive value
while type(el) is dict or type(el) is list:
if type(el) is list:
# if el is a list, try using one of the indicies passed
el = el[indices.pop()]
else:
# otherwsie, go along the path specified
el = el[path.pop(0)]
return el
Note that list.pop()
removes an element from a list, then returns the element it removed. So, el[indices.pop()]
removes an index from indices
, then indexes el
with that index (see the documentation for more).
This function takes three parameters, the dictionary to transverse, a list of keys, and a list of indices to use. Indicies will be taken off the beginning of indices
. In your specific case, you can call it like this:
getKey(json_obj, ['key1', 'key2', 'key3', 'key4'], [idx, idx]);
I’m new to json, and I’m having trouble dealing with indexing keys that usually have sub-array but sometimes they don’t.
Usually, key2 and key3 contain sub-array:
json_obj = json.loads(x)
json_obj["key1"]["key2"][idx]["key3"][idx]["key4"]
However, sometimes key2 and/or key3 is no longer an array
executing above code would throw an exception
to retrieve key4:
json_obj["key1"]["key2"]["key3"][idx]["key4"]
json_obj["key1"]["key2"][idx]["key3"]["key4"]
json_obj["key1"]["key2"]["key3"]["key4"]
Is there an elegant way to retrieve key4 regardless the condition of key2 and key3?
All you need to do is transverse the tree, getting the next key if the value is a dictionary or getting an index if the value is a list. Here is a function to do that general behavior:
def getKey(data, path, indices):
el = data
# keep transversing until we find a primitive value
while type(el) is dict or type(el) is list:
if type(el) is list:
# if el is a list, try using one of the indicies passed
el = el[indices.pop()]
else:
# otherwsie, go along the path specified
el = el[path.pop(0)]
return el
Note that list.pop()
removes an element from a list, then returns the element it removed. So, el[indices.pop()]
removes an index from indices
, then indexes el
with that index (see the documentation for more).
This function takes three parameters, the dictionary to transverse, a list of keys, and a list of indices to use. Indicies will be taken off the beginning of indices
. In your specific case, you can call it like this:
getKey(json_obj, ['key1', 'key2', 'key3', 'key4'], [idx, idx]);