【问题标题】:Print unique JSON keys in dot notation using Python使用 Python 以点表示法打印唯一的 JSON 键
【发布时间】:2016-02-03 00:29:34
【问题描述】:

我正在尝试编写一个脚本,该脚本将以点表示法打印 JSON 文件的唯一键,以便快速分析结构。

例如,假设我有以下格式的“myfile.json”:

{
"a": "one",
"b": "two",
"c": {
    "d": "four",
    "e": "five",
    "f": [
        {
            "x": "six",
            "y": "seven"
        },
        {
            "x": "eight",
            "y": "nine"
        }
    ]
}

运行以下将产生一组唯一的键,但它缺少沿袭。

import json
json_data = open("myfile.json")
jdata = json.load(json_data)

def get_keys(dl, keys_list):
    if isinstance(dl, dict):
        keys_list += dl.keys()
        map(lambda x: get_keys(x, keys_list), dl.values())
    elif isinstance(dl, list):
        map(lambda x: get_keys(x, keys_list), dl)

keys = []
get_keys(jdata, keys)

all_keys = list(set(keys))

print '\n'.join([str(x) for x in sorted(all_keys)])

以下输出并不表示 'x'、'y' 嵌套在 'f' 数组中。

a
b
c
d
e
f
x
y

我不知道如何循环遍历嵌套结构以附加父键。

理想的输出是:

a
b
c.d
c.e
c.f.x
c.f.y

【问题讨论】:

  • 你已经很好地遍历了get_keys中的dict,为什么不在函数内部打印?

标签: python json python-2.7


【解决方案1】:

我建议使用递归生成器函数,使用 yield 语句而不是在内部构建列表。在 Python 2.6+ 中,以下工作:

import json
json_data = json.load(open("myfile.json"))

def walk_keys(obj, path=""):
    if isinstance(obj, dict):
        for k, v in obj.iteritems():
            for r in walk_keys(v, path + "." + k if path else k):
                yield r
    elif isinstance(obj, list):
        for i, v in enumerate(obj):
            s = "[" + str(i) + "]"
            for r in walk_keys(v, path + s if path else s):
                yield r
    else:
        yield path


for s in sorted(walk_keys(json_data)):
    print s

在 Python 3.x 中,您可以使用 yield from 作为递归生成的语法糖,如下所示:

import json
json_data = json.load(open("myfile.json"))

def walk_keys(obj, path=""):
    if isinstance(obj, dict):
        for k, v in obj.items():
            yield from walk_keys(v, path + "." + k if path else k)
    elif isinstance(obj, list):
        for i, v in enumerate(obj):
            s = "[" + str(i) + "]"
            yield from walk_keys(v, path + s if path else s)
    else:
        yield path


for s in sorted(walk_keys(json_data)):
    print(s)

【讨论】:

    【解决方案2】:

    根据 MTADD 的指导,我整理了以下内容:

    import json
    
    json_file_path = "myfile.json"
    json_data = json.load(open(json_file_path))
    
    def walk_keys(obj, path = ""):
        if isinstance(obj, dict):
            for k, v in obj.iteritems():
                for r in walk_keys(v, path + "." + k if path else k):
                    yield r
        elif isinstance(obj, list):
            for i, v in enumerate(obj):
                s = ""
                for r in walk_keys(v, path if path else s):
                    yield r
        else:
            yield path
    
    all_keys = list(set(walk_keys(json_data)))
    
    print '\n'.join([str(x) for x in sorted(all_keys)])
    

    结果符合预期

    a
    b
    c.d
    c.e
    c.f.x
    c.f.y
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-15
      • 1970-01-01
      • 1970-01-01
      • 2016-02-01
      相关资源
      最近更新 更多