Created
February 26, 2018 21:22
-
-
Save ace0/69350ef62c72c06fe65d8435be860e6a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Quickly find paths to keys or values deeply embedded in complex structures of JSON. | |
Written in python 3. | |
Example: | |
sampleStructure = { | |
'AmiLaunchIndex': 0, | |
'Monitoring': { | |
'State': 'disabled' | |
}, | |
'Placement': { | |
'AvailabilityZone': 'us-east', | |
'GroupName': '', | |
'Tenancy': 'default' | |
} | |
} | |
print(search('Tenancy', sampleStructure)) | |
""" | |
def search(target, structure, variableName="structure"): | |
""" | |
Search for a @target key or value in a possibly nested @search. | |
@return a list of printable strings that show the location and value of the target. | |
""" | |
def fmt(path, value): | |
return "{}{} == {}".format(variableName, strFromPath(path), value) | |
return [fmt(p,v) for p,v in _searchRecursive(target, structure, [])] | |
def strFromPath(path): | |
""" | |
Construct a string that represents the Python code required to retrieve a value from | |
the structure. | |
""" | |
def fmt(x): | |
if type(x) == str: | |
return "['{}']".format(x) | |
elif type(x) == int: | |
return "[{}]".format(x) | |
else: | |
return x | |
return ''.join([fmt(x) for x in path]) | |
def _searchRecursive(target, structure, path, debugOutput=False): | |
""" | |
Receursively descends a structure in search of a target target or value. | |
@yields: ([path], value) | |
""" | |
if debugOutput: | |
print("\tSearching: {}".format(path)) | |
# Base case: finding the target in a dcitionary | |
if type(structure) == dict and target in structure: | |
yield path + [target], structure[target] | |
# Base case: matching terminal value | |
if target == structure: | |
yield path, target | |
# Lists | |
if type(structure) == list: | |
for i, item in enumerate(structure): | |
yield from _searchRecursive(target, item, path + [i]) | |
# Dictionaries | |
if type(structure) == dict: | |
for k,v in structure.items(): | |
yield from _searchRecursive(target, v, path + [k]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment