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

时间:2017-05-04 12:52:57

标签: 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',{})

3 个答案:

答案 0 :(得分:0)

很简单地在`get(' phones')中使用一个列表,默认为一个空dict,即:

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

请注意,如果IndexError为空列表,则仍会以r["profile"]["phones"]为中断。你可以使用or,即:

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

但是它变得非常混乱(并且没有充分的理由建立两个空的序列和列表),因此,对于更明确的代码,你可能会更好,参见Pankaj Singhal的回答。 / p>

答案 1 :(得分:0)

您的方法非常不理想,因为根词典中缺少的profile键不会终止搜索,但会继续不必要的。显然,空字典中没有任何键。

您可以使用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'])

答案 2 :(得分:0)

这个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'))