使用Python为所有key递归映射一个JSON文件,同时记录每个key的"nesting"深度

Using Python to recursively map a JSON file for all keys, while also recording the depth of "nesting" for each key

背景:

我有一个很大的 JSON 文件(数十 GB),其中文件的每一“行”都是一个日志条目(也是 JSON 格式)。日志来自多个不同的来源,因此一个日志中的字段可能会或可能不会显示在任何其他日志中。换句话说,JSON 格式的“键”,以及键相互嵌套的程度,在日志之间是不一致的。

我的目标:

我需要能够找到任何给定日志中的所有键 [已完成],并跟踪哪些键嵌套在哪些其他键下 [这是我还没有解决的部分].

我目前的工作:

由于文件太大,我无法一次将文件全部加载到内存中,所以我一直在逐行检查它(逐个日志)。我已经编辑了实际内容,但假设文件的第一行(日志)如下所示:

{'foo': {'bar': 'data',
         'biz': 'data'},
 'baz': 'data',
 'qux': {'quux': 'data',
         'quuz': 'data'},
 'corge': {'grault': {'garply': 'data'},
           'waldo': {'fred': 'data',
                     'plugh': 'data'},
           'xyzzy': 'data'},
 'thud': 'data'}

我一直在使用这个代码...

def find_nested_dicts(d):
    for k,v in d.items():
        KEYS.append(k)
        if isinstance(d[k], dict):
            find_nested_dicts(d[k])
    return KEYS

KEYS=[]
with open(full_geodata_path, "r") as f:
    next_line = f.readline()
    next_line_json = json.loads(next_line)
    output = find_nested_dicts(next_line_json)

...产生这个:

output = [
    'foo', 
    'bar', 
    'biz', 
    'baz', 
    'qux', 
    'quux', 
    'quuz', 
    'corge', 
    'grault', 
    'garply', 
    'waldo',
    'fred', 
    'plugh',
    'xyzzy',
    'thud'
]

我不喜欢使用 KEYS 作为全局变量,但我无法让它在本地工作。

请注意,每个键附加到此列表的顺序很重要。键的名称很少包含任何指示它们嵌套在哪个父键下的内容。换句话说,我有意编写代码,以便将键附加到 output 列表的顺序与它们以 JSON 格式显示的顺序相同。

上面显示的结果是我的目标的一半。但是,我希望能够生成一个包含每个键的列表,以及检索它的嵌套深度。我正在尝试构建一个如下所示的列表:

output = [ 
    ('foo', 0), 
    ('bar', 1), 
    ('biz', 1), 
    ('baz', 0), 
    ('qux', 0), 
    ('quux', 1), 
    ('quuz', 1), 
    ('corge', 0), 
    ('grault', 1), 
    ('garply', 2), 
    ('waldo', 1),
    ('fred', 2), 
    ('plugh', 2),
    ('xyzzy', 1),
    ('thud', 0)
]

这个函数可能是我得到的最接近的函数:

def find_nested_dicts(d, depth=0):
    for k, v in d.items():
        KEYS.append((k, depth))
        depth += 1
        if isinstance(v, dict):
            find_nested_dicts(v, depth)
        else:
            depth -= 1
    return KEYS

此尝试的问题是此函数只会导致“深度”计数器增加。

我尝试将递归映射到纸上,并尝试在 depth += 1depth -= 1KEYS.append((k, depth)) 语句中移动 forif 以各种组合循环,希望获得更好的结果。

在这一点上,我不确定是否是我自己无法完全概念化递归,或者我正在尝试做的事情是否真的可以用普通 python 实现。非常感谢任何见解。

最后一点,我没有我试图解决此问题的机器的管理员权限,并且无法从我的个人机器访问此数据。从以前的项目中我知道我可以使用以下库:

import numpy as np
import os
import pandas as pd
import json
import itertools
from collections import Counter
import matplotlib.pyplot as plt
def foo(d, arr, n):
    if isinstance(d, dict):
        for k in d.keys():
            arr.append((k, n))
            foo(d[k], arr, n + 1)
            
ans = []
foo(data, ans, 0)
ans
# [('foo', 0),
#  ('bar', 1),
#  ('biz', 1),
#  ('baz', 0),
#  ('qux', 0),
#  ('quux', 1),
#  ('quuz', 1),
#  ('corge', 0),
#  ('grault', 1),
#  ('garply', 2),
#  ('waldo', 1),
#  ('fred', 2),
#  ('plugh', 2),
#  ('xyzzy', 1),
#  ('thud', 0)]