Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 展平JSON/字典/列表_Python_Json_Nested_Flatten - Fatal编程技术网

Python 展平JSON/字典/列表

Python 展平JSON/字典/列表,python,json,nested,flatten,Python,Json,Nested,Flatten,我有一个嵌套的JSON { "ID": 300, "Name": " TEST", "Value": [ { "Details": [ { "Name": "TEST1", "

我有一个嵌套的JSON

{
    "ID": 300,
    "Name": " TEST",
    "Value": [
        {
            "Details": [
                {
                    "Name": "TEST1",
                    "Value": "XXXXXX"
                },
                {
                    "Name": "TEST2",
                    "Value": "DDDDDDDD"
                }
            ],
            "Time": [ 1600358400, 1600358700, 1600359000],
            "Values": [ 0, 0, 0]
        }
    ]
}
我想将json展平,以便能够得到如下列表

我使用了itertools groupby,但无法达到预期的效果。它正在水平变平

代码我已经试过了

from itertools import groupby
import json

def myflatten(d, depth=0):
    rv = [({}, depth)]
    if isinstance(d, dict):
        for k, v in d.items():
            if not isinstance(v, dict) and not isinstance(v, list):
                for i in rv:
                    i[0][k] = v
            else:
                for (vv, _depth) in myflatten(v,depth+1):
                    rv.append((rv[-1][0].copy(), _depth))
                    for kkk, vvv in vv.items():
                        rv[-1][0][kkk] = vvv
    elif isinstance(d, list):
        for v in d:
            rv.append((rv[-1][0].copy(), depth+1))
            for (vv, _) in myflatten(v,depth+1):
                for kkk, vvv in vv.items():
                    rv[-1][0][kkk] = vvv
    for i, _depth in rv:
        yield i, _depth

out = []

a = {
    "ID": 300,
    "Name": " TEST",
    "Value": [
        {
            "Details": [
                {
                    "Name": "TEST1",
                    "Value": "XXXXXX"
                },
                {
                    "Name": "TEST2",
                    "Value": "DDDDDDDD"
                }
            ],
            "Time": [ 1600358400, 1600358700, 1600359000],
            "Values": [ 0, 0, 0]
        }
    ]
}

for v, g in groupby(sorted(myflatten(a), key=lambda k: -k[1]), lambda k: k[1]):
    out.extend(i[0] for i in g)
    break
print(out)

有人能帮助将嵌套的json/dict/list垂直展平而不是水平展平吗?最终的目标是能够在RDBMS中存储数据,而不必无限增加列数,而是行数。

因为在您的情况下,您需要将行(或记录)存储在数据库中,所以您可以使用一个函数生成字典列表,您可以迭代地将其添加到数据库中。此外,由于代码看起来太过嵌套,您可能会考虑以下代码片段:

def flatten(dictionary):
    my_list = []
    _id = dictionary["id"]
    name = dictionary["Name"]

    for obj in dictionary["Value"]:
        details = obj["Details"]
        time = obj["Time"]
        vals = obj["Values"]

        for i in range(len(time)):
            for (index, detail_obj) in enumerate(details):
                my_list.append({
                    "ID": _id,
                    "Name": name,
                    "Details.ID": index,
                    "Details.Name": detail_obj["Name"]
                    "Details.Value": detail_obj["Value"],
                    "Time.ID": i,
                    "Time.Time": time[i],
                    "Time.Value": vals[i]
                })

    return my_list

注意:此函数将一次处理一个嵌套字典(如您在问题中提供的字典)。因此,如果您有多个这样的嵌套字典,您可能希望为这些嵌套字典中的每一个调用此函数。

为了概括这一点,我们需要将所有内容展平,但将迭代器返回列表。然后我们将把这些迭代器压缩在一起,使它们以相同的速度前进。但这些迭代器可能是自己必须被压扁的指令,记住它们来自的继承权

此外,请注意,外部dict的ID、Name和Value不受所有这些限制,并且不包括在递归命名方案中,因此我们将编写一个顶级处理程序来解析这些内容,然后设置其余内容。“Details.ID”不是数据的一部分,所以我硬编码了它,ID取自前面提到的列表zip上的enumerate

我承认,将flatte函数推广到处理dict、list和标量数据的任意嵌套对我来说有点过分,因为我们需要为几种不同类型的输入链接迭代器并选择一致的返回类型。太多了

相反,我在有限的范围内使用数据结构,并假设只有一个级别有列表。我只在数据中变平。这大大简化了问题,同时仍然在所有级别接受任意名称和值:

import itertools, json, typing, pprint

# top level function starts recursion
def parse(data):
    fixed_fields = {k:v for k,v in data.items() if not isinstance(v, typing.Iterable)}
    for testcase in data['Value']:
        for testcase in data['Value']:
            for record in parse_testcase(testcase):
                record.update(fixed_fields)
                yield record

def parse_testcase(testcase):
    names = []
    values = []
    for key, value in testcase.items():
        names.append(key)
        values.append(itertools.chain(value))
    
    for details_id, row in enumerate(zip(*values)):
        record = {'Details.ID': details_id}
        for name, value in zip(names, row):
            if isinstance(value, dict):
                flatten(name, value, record)
            else:
                record[name] = value
        yield record
        
def flatten(parent_key, details, result):
    for key, value in details.items():
        keyname = get_keyname(parent_key, key)
        if isinstance(value, dict):
            flatten(keyname, value, result)
        else:
            result[keyname] = value

def get_keyname(parent_key, key):
    if parent_key:
        return '.'.join((parent_key, key))
    return key

text = """{
    "ID": 300,
    "Name": " TEST",
    "Value": [
        {
            "Details": [
                {
                    "Name": "TEST1",
                    "Value": "XXXXXX"
                },
                {
                    "Name": "TEST2",
                    "Value": "DDDDDDDD"
                }
            ],
            "Time": [ 1600358400, 1600358700, 1600359000],
            "Values": [ 0, 0, 0]
        }
    ]
}"""

for record in parse(json.loads(text)):
    pprint.pprint(record)
由于您有2条详细信息记录和3条其他记录,我不得不怀疑您的预期输出是错误的。我能理解的唯一解析规则是同步推进所有列表,因此删除额外的时间和值度量。如果您能帮助我理解解析规则,以便我理解您是如何得到四行的,我们可以重新讨论这个问题。我得到:

{'Details.ID':0,
'Details.Name':'TEST1',
'Details.Value':'XXXXXX',
“ID”:300,
“时间”:1600358400,
“值”:0}

{'Details.ID':1,
'Details.Name':'TEST2',
'Details.Value':'DDDDDDDD',
“ID”:300,
“时间”:1600358700,
“值”:0}


我还注意到,您的输出具有由输入确定的任意方案。也许输出一个csv文件,并将其装配到关系数据库中作为一项单独的任务是明智的。

您的代码缩进错误。请把它修好。另外,请发布您现在得到的信息,并通过创建一个“接近解决方案:按照以下指导编辑代码”来缩小错误源Pranav@nomad请指定所需的输出。由于无法推断所需的结构,因此图像不计数。。。您希望它是一个列表列表吗?您希望总体上平坦化,还是使用输入的领域知识?zip(详细信息、值)如何?这看起来像是领域知识,尽管我们可以自动压缩最外层列表下面的任何列表。谢谢,我现在可以尝试一下。但在这个等待中,我必须在json中始终具有相同的键和相同的嵌套列表。在我的情况下,它可能会有所不同。我正在尝试使用这里提供的功能。我仍然有一些问题,但这是非常接近我需要的。你能描述一下它到底是以什么方式变化的吗?我可以有另一个具有嵌套值的键,就像details键一样。我仍然可以使用您的代码使其工作,但每次我将有一个新的嵌套键,我可以手动更新代码如果正确的输出应该有四行,只要让我知道,我可以更新或删除这个答案。我不明白你怎么知道的。如果它是多个表的外部连接,也许我们应该单独解析这些表。因为我们有多个“时间”,我们应该有同样多的结果。但我理解你的想法。