通过嵌套json递归迭代python中的特定键

Posted

技术标签:

【中文标题】通过嵌套json递归迭代python中的特定键【英文标题】:recursive iteration through nested json for specific key in python 【发布时间】:2014-01-28 12:30:01 【问题描述】:

我正在尝试从 json 文件中提取嵌套值。我想打印出每个“id”键的每个值。我想我很接近但无法弄清楚为什么 obj 类型从字典变为列表,然后为什么我无法解析该列表。 这是我正在使用的 json 的链接:http://hastebin.com/ratevimixa.tex

这是我当前的代码:

#!/usr/bin/env python
#-*- coding: utf-8 -*-

import json

json_data = open('JubJubProductions.json', 'r+')
jdata = json.loads(json_data.read().decode("utf-8"))

def recursion(dict):

    for key, value in dict.items():

        if type(value) == type(dict):
            if key != "paging":
                for key, value in value.items():
                    if isinstance (value,list):
                        print key
                        # place where I need to enter list comprehension?
                if type(value) == type(dict):
                    if key == "id":
                        print " id found " + value
                    if key != "id":
                        print key + " 1st level"
                if key == "id":
                    print key
        else:
            if key == "id":
                print "id found " + value       
if __name__ == '__main__':
    recursion(jdata)

----------------------------------------------- --------------------------------------------------------更新强>

这就是我现在正在使用的,它会返回一个 id 值,但不是全部:

#!/usr/bin/env python
#-*- coding: utf-8 -*-

import json

json_data = open('jubjubProductions', 'r+')
jdata = json.loads(json_data.read().decode("utf-8"))

def id_generator(d):
    for k, v in d.items():
        if k == "id":
            yield v
        elif isinstance(v, dict):
            for id_val in id_generator(v):
                yield id_val

if __name__ == '__main__':
    for _ in id_generator(jdata):
        print (_)

【问题讨论】:

当我使用它时,我得到一个错误“太多的值无法解压”。我没有使用 d.items() 否则我会得到“AttributeError: 'unicode' object has no attribute 'items'” 【参考方案1】:

扩展至python 3.x answer: 如果嵌套 json 在不同的列表或字典下具有相似的键,并且您想取它的第一个值.. 以下是通用方式:

 def get_value_from_generator(json_input, lookup_key):
        value = list(item_generator(json_input, lookup_key))
        val = value[0] if value else None
        print(f'lookup_key -> value : val')
        return val
def item_generator(json_input, lookup_key):
    if isinstance(json_input, dict):
        for k, v in json_input.items():
            print(f'k -- v')
            if k == lookup_key:
                yield v
            else:
                yield from item_generator(v, lookup_key)
    elif isinstance(json_input, list):
        for item in json_input:
            yield from item_generator(item, lookup_key)

【讨论】:

【参考方案2】:
def get_val(j, s, v=None):
for k in j:
    if v == None and k == s:
        return j[k]
    elif v != None and k == s and v == j[k]:
        return True
    elif v != None and k == s and v != j[k]:
        return False
    elif isinstance(j[k], dict):
        return get_val(j[k], s, v)

你可以在下面的 json 列表中使用 with,

for l in j:
    r = get_val(l, 'key')
    print(r)

for l in j:
    r = get_val(l, 'mac', '00-60-2F-5A-04-51')
    print(r)

【讨论】:

【参考方案3】:

更简洁的代码(在 python 3.x 中)。

def parse_json_recursively(json_object, target_key):
    if type(json_object) is dict and json_object:
        for key in json_object:
            if key == target_key:
                print(": ".format(target_key, json_object[key]))
            parse_json_recursively(json_object[key], target_key)

    elif type(json_object) is list and json_object:
        for item in json_object:
            parse_json_recursively(item, target_key)


json_object = "key1": "val1", "key2": ["key3":"val3", "key4": "val4", 123, "abc"]
target_key = "key3"
parse_json_recursively(json_object, target_key) # Ouput key3: val3

【讨论】:

很好......我被困住了......如果我想要方法/函数的返回值而不仅仅是打印【参考方案4】:
def id_generator(dict_var):
    for k, v in dict_var.items():
        if k == "id":
            yield v
        elif isinstance(v, dict):
            for id_val in id_generator(v):
                yield id_val

这将创建一个迭代器,它将产生键“id”下任何级别的每个值。示例用法(打印所有这些值):

for _ in id_generator(some_json_dict):
    print(_)

【讨论】:

在最后的 if name == main 语句之后添加 for 循环打印? 取决于您的需要。这段代码将提取您需要的所有值。做你想做的最简单的方法是用 id_generator 替换你的“recursion”函数,然后用“jdata”而不是“some_json_dict”来代替你的“recursion(jdata)” 我就是这么想的。我这样做了,现在得到“TypeError:arg 2 must be a class, tuple or tuple of classes and types” 是的......因为我犯了一个错误并称参数为“dict”:P 将所有出现的“dict”更改为其他任何东西(“d”、“dict_”、任何)。然后我会说它会起作用。我没有运行就写好了。 Bo Sunesen 的答案似乎更合适,因为对象列表。【参考方案5】:

JSON 可能包含需要搜索的对象列表:

Python 2.7 版本:

def item_generator(json_input, lookup_key):
    if isinstance(json_input, dict):
        for k, v in json_input.iteritems():
            if k == lookup_key:
                yield v
            else:
                for child_val in item_generator(v, lookup_key):
                    yield child_val
    elif isinstance(json_input, list):
        for item in json_input:
            for item_val in item_generator(item, lookup_key):
                yield item_val

Python 3.x 版本:

def item_generator(json_input, lookup_key):
    if isinstance(json_input, dict):
        for k, v in json_input.items():
            if k == lookup_key:
                yield v
            else:
                yield from item_generator(v, lookup_key)
    elif isinstance(json_input, list):
        for item in json_input:
            yield from item_generator(item, lookup_key)

【讨论】:

在 python3 中,使用 dict.items() 而不是 dict.iteritems() 我更新了答案以反映来自@IlyaRusin 的评论 这是正确的答案,因为它也处理列表。你可以使用yield from 让它更漂亮一点。 我更新了答案以包含带有yield from 表达式的python 3.x 版本。

以上是关于通过嵌套json递归迭代python中的特定键的主要内容,如果未能解决你的问题,请参考以下文章

SQLAlchemy JSON列包含嵌套json中的特定键

模块调用,datetime,time,logging,递归,双层装饰器, json,pickle迭代器和生成器

如何在没有外部递归函数的情况下解析多个嵌套的 JSON 键?

Medium | LeetCode 341. 扁平化嵌套列表迭代器 | 递归 | 栈

python--递归函数匿名函数嵌套函数高阶函数装饰器生成器迭代器

python递归排序所有嵌套的iterable