Python:JSON从字典列表中获取价值,或者如果列表为空,则打印某些内容



我正在尝试解析我从Web API获得的JSON响应。问题在于,JSON可以具有不同的级别,可以转化为字典的字典,并在混音中偶尔列出。示例(这起作用(:

for r in json_doc['results']:
    yield r.get('lastLoginLocation',{}).get('coordinates',{}).get('lat',{})

当其中的字典列表列表时,我可以做同样的事情吗?如果列表为空,我希望它可以从列表中的第一个字典返回列表中的第一个字典的指定键值,如果列表为空(列表为空(。

示例(这不起作用(

   yield r.get('profile',{}).get('phones',{})[0].get('default',{})

在`get('phones'(中使用一个空dict的列表,即默认值,即:

yield r.get('profile',{}).get('phones',[{}])[0].get('default',{})

请注意,如果r["profile"]["phones"]是一个空列表,则仍然会与IndexError中断。您可以使用or,即:

yield (r.get('profile',{}).get('phones',[{}]) or [{}])[0].get('default',{})

但是它确实变得凌乱(并且没有充分的理由构建两个空的命令和列表(,因此您可能会更好地说明更明确的代码,cf pankaj singhal的答案。

您的方法非常卑鄙,因为root字典中缺少的 profile键不会终止搜索,但在不必要的上继续进一步。显然在空的dict中不会有任何钥匙。

您可以使用try/except

def get_value(container, keys=None)
    if keys is None: 
        raise ValueError
    for r in container:
        item = r
        for i in keys:
            try:
                item = item[i]
            except (IndexError, KeyError):
                yield {}
                break
        # finished cleanly
        else:
            yield item

get_value(json_doc['results'], keys=['profile', 'phones', 0, 'default'])

get_nested辅助功能可能是您想要的。过去,我在某些XML解析代码中使用了类似的技术。它删除了通过掩盖您的代码实际试图实现的目标而实现。

from contextlib import suppress
def get_nested(list_or_dict, keys, default={}):
    """Get value from nested list_or_dict using keys. If the current
    level is a dict, lookup the current key. If the current
    level is a list, lookup current key in the first element of the
    list. Return default for any errors.
    """
    def get(item, key):
        if hasattr(item, 'get') and key in item:
            return item[key]
        raise KeyError
    for key in keys:
        with suppress(KeyError):
            list_or_dict = get(list_or_dict, key)
            continue
        with suppress(IndexError, KeyError):
            list_or_dict = get(list_or_dict[0], key)
            continue
        break
    else:
        return list_or_dict
    return default

您的代码将是这样的:

for r in json_doc['results']:
    yield get_nested(r, ('lastLoginLocation', 'coordinates', 'lat'))
    yield get_nested(r, ('profile', 'phones', 'default'))

最新更新