Python Chained Get() Method With List Element Inside Json
[Python 2.7] I have a JSON source that doesn't always return the full list of expected keys. I'm using chained gets() to address this. d = {'a': {'b': 1}} print(d.get('a', {}).get
Solution 1:
I agree with @stovfl that writing your own lookup function is the way to go. Although, I don't think a recursive implementation is necessary. The following should work well enough:
def nested_lookup(obj, keys, default='NA'):
current = obj
for key in keys:
current = current if isinstance(current, list) else [current]
try:
current = next(sub[key] forsubincurrentifkeyinsub)
exceptStopIteration:
returndefaultreturncurrentd = {'a': {'b': [{'c': 2}, {'d': 3}]}}
print nested_lookup(d, ('a', 'b', 'c')) # 2print nested_lookup(d, ('a', 'b', 'd')) # 3print nested_lookup(d, ('a', 'c')) # NA
The class approach doesn't seem great because you're going to be creating a lot of unnecessary objects and if you're ever trying to lookup a node that isn't a leaf, then you're going to wind up with a custom object rather than the actual node object.
Solution 2:
Question: I can't use a get() ... because lists don't support the get().
You can implement your own
list.get()
, for instance:classmyGET(object): def__init__(self, data): ifisinstance(data, dict): self.__dict__.update(data) ifisinstance(data, list): for d in data: self.__dict__.update(d) defget(self, key, default=None): ifhasattr(self, key): _attr = object.__getattribute__(self, key) ifisinstance(_attr, (list, dict)): return myGET(_attr) else: return _attr else: return default d = {'a': {'b': [{'c': 2}]}} myGET(d).get('a', {}).get('b', []).get('c', 'NA') >>> 2 myGET(d).get('a', {}).get('b', []).get('d', 'NA') >>> NA
A recursive Solution, no need to chaining, for instance:
defget(_dict, subkey, default): def_get(_dict, key, deep): if key == subkey[deep]: if deep == len(subkey) - 1: return _dictelse: return _get(_dict, None, deep + 1) elifisinstance(_dict, dict): for k in _dict: match = _get(_dict[k], k, deep) if match: return match elifisinstance(_dict, list): for e in _dict: match = _get(e, None, deep) if match: return match ifnotisinstance(subkey, (tuple, list)): subkey = (subkey) _r = _get(_dict, None, 0) ifnot _r: return default else: return _r get(d, 'c', 'NA') >>> 2 get(d, 'd', 'NA') >>> NA # get a inside b d = {'a': {'b': [{'a': 3}, {'c': 2}]}} get(d, ('b', 'a'), 'NA') >>> 3
Tested with Python: 3.4.2 and 2.7.9
Post a Comment for "Python Chained Get() Method With List Element Inside Json"