在嵌套字典中获取JSON键路径

5
json = '{
    "app": {
        "Garden": {
            "Flowers": {
                "Red flower": "Rose",
                "White Flower": "Jasmine",
                "Yellow Flower": "Marigold"
            }
        },
        "Fruits": {
            "Yellow fruit": "Mango",
            "Green fruit": "Guava",
            "White Flower": "groovy"
        },
        "Trees": {
            "label": {
                "Yellow fruit": "Pumpkin",
                "White Flower": "Bogan"
            }
        }
    }'

这是我的JSON字符串,它经常变化,所以字典中的键的位置每次都不同,我需要搜索一个键并打印其对应的值。由于JSON字符串每次都会改变,我编写了一个递归函数(见下文)来搜索新的JSON字符串中的键并打印值。然而,现在的情况是,我们有相同的键多次出现,但值不同,我该如何获取键的完整路径,以便更容易理解它是哪个键的值?例如,结果应该像这样:
app.Garden.Flowers.white Flower = Jasmine
app.Fruits.White Flower = groovy
app.Trees.label.White Flower = Bogan

我的代码到目前为止:

import json
with open('data.json') as data_file:    
  j = json.load(data_file)


def find(element, JSON):    
  if element in JSON:
    print JSON[element].encode('utf-8')
  for key in JSON:
    if isinstance(JSON[key], dict):
      find(element, JSON[key])
 


find(element to search,j)

        
4个回答

2
您可以添加一个字符串参数,用于跟踪当前的JSON路径。以下类似的内容可能适用:
def find(element, JSON, path, all_paths):    
  if element in JSON:
    path = path + element + ' = ' + JSON[element].encode('utf-8')
    print path
    all_paths.append(path)
  for key in JSON:
    if isinstance(JSON[key], dict):
      find(element, JSON[key],path + key + '.',all_paths)

您需要这样调用它:
all_paths = []
find(element_to_search,j,'',all_paths)

谢谢...然而这是一个递归函数并且在结尾处返回None..我们能修复它吗? - min2bro
从函数中返回多个值会很棘手。更简单的方法是使用一个列表作为参数,就像我在这个编辑版本中添加的那样,它可以收集所有最终路径。在调用函数后,all_paths 将拥有所有被打印出来的数据。 - Blair
第7行,在find函数中 path = path + element + ' = ' + JSON[element].encode('utf8') UnicodeDecodeError: 'ascii'编解码器无法解码第3个位置的0xc3字节:超出范围(128) - min2bro
那是一个独立的问题。如果你无法弄清楚出了什么问题,就提出一个独立的问题,并提供你所知道的所有信息。 - Blair
希望我能自己解决这个问题...感谢迄今为止所有的帮助...干杯.. - min2bro
1
我单独发布了这个问题,无法调试为什么由于值中的特殊字符而出现此问题。http://stackoverflow.com/questions/31011731/ascii-codec-cant-decode-byte-0xc3-in-position-3 - min2bro

0
def getDictValueFromPath(listKeys, jsonData):
    """
    >>> mydict = {
        'a': {
            'b': {
                'c': '1'
            }
        }
    }
    >>> mykeys = ['a', 'b']
    >>> getDictValueFromPath(mykeys, mydict)
    {'c': '1'}
    """
    localData = jsonData.copy()
    for k in listKeys:
        try:
            localData = localData[k]
        except:
            return None
return localData

代码片段


0
以下代码片段将提供一个可在JSON中访问的路径列表。它遵循JSON路径的约定,其中[]表示该路径是一个列表。
def get_paths(source):
    paths = []
    if isinstance(source, collections.abc.MutableMapping):
        for k, v in source.items():
            if k not in paths:
                paths.append(k)
            for x in get_paths(v):
                if k + '.' + x not in paths:
                    paths.append(k + '.' + x)
    elif isinstance(source, collections.abc.Sequence) and not isinstance(source, str):
        for x in source:
            for y in get_paths(x):
                if '[].' + y not in paths:
                    paths.append('[].' + y)
    return paths

-1
这是 Brian 回答的修改版本,支持列表并返回结果:
def find(element, JSON, path='', all_paths=None):
    all_paths = [] if all_paths is None else all_paths
    if isinstance(JSON, dict):
        for key, value in JSON.items():
            find(element, value, '{}["{}"]'.format(path, key), all_paths)
    elif isinstance(JSON, list):
        for index, value in enumerate(JSON):
            find(element, value, '{}[{}]'.format(path, index), all_paths)
    else:
        if JSON == element:
            all_paths.append(path)
    return all_paths

使用方法:

find(JSON, element)

它对我不起作用。 - Bemojo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接