在Python中将CSV转换为JSON:如何去除多余的括号

vxbzzdmp  于 2023-07-31  发布在  Python
关注(0)|答案(1)|浏览(83)

经过大量的工作,我有代码创建JSON输出时,我需要通过它运行CSV。
下面是CSV的示例:
insert_topic,学术课程,类|教室|(课程材料)~3....
insert_topic,学术质量,"((学习成果)~3|(学习期望)~3)|学习
insert_topic,学术支持,(可用教师)~3|(可用教员)~3...
下面是代码:

import csv
import json
from itertools import groupby

csvfile = open('TIQ_dict_topics.csv', 'r').readlines()
jsonfile = open('Topics.json', 'w')
 
r = csv.DictReader(csvfile)
data = [dict(d) for d in r]
groups = []
 
for k, g in groupby(data, lambda r: (r['label'], r['operation'])):
    groups.append({
        "operation": k[1],
        "topic": [{k: v for k, v in d.items() if k not in ['operation']} for d in list(g)]
        })

out=json.dumps(groups[:], indent=4)

jsonfile.write(out)

字符串
下面是输出:

[
    {
        "operation": "insert_topic",
        "topic": [
            {
                "label": "Academic Program",
                "query": "lots here..."
            }
        ]
    },
    {
        "operation": "insert_topic",
        "topic": [
            {
                "label": "Academic Quality",
                "query": "..."
            }
        ]
    },


一切都是伟大的,除了有方括号是不必要的,我必须删除,以使用这个文件在程序中,我使用它。(方括号为粗体。)
[ {“operation”:“insert_topic”,“topic”:[{“label”:“学术课程”,“查询”:“lots here...”}]},
代码的哪一部分是写那些方括号的,有没有一种简单的方法可以在不重写所有内容的情况下去掉那些方括号?
我已经尝试了互联网上的每一个CSV到JSON解决方案。这是我最接近我需要的结构。在这个项目之前,我还没有使用JSON很多,所以我仍然在学习JSON代码的哪些部分做什么。

watbbzwu

watbbzwu1#

如果没有看到一些输入CSV(可能不止一点),我不能肯定itertools.groupby有什么好的功能。我没有看到你在使用它之前对行进行排序,从groupby的文档中:
通常,可迭代对象需要已经在同一个键函数上排序。
你知道CSV在你打开它之前已经按(label, operation)排序了吗?
我想对你的计划提出如下修改建议。
我假设你的CSV看起来像这样:

operation,label,query
op1,label1,query1
op1,label1,query2
op1,label2,query3
op2,label3,query4
op2,label4,query5
op2,label3,query6

字符串
你可以直接在文件上创建一个DictReader,不需要读取行然后将列表传递给DictReader:

with open("input.csv", newline="", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    rows = list(reader)


list(reader)将迭代器转换为实际的dicts列表;不是绝对必要的,但如果/当你需要调试它时,它会帮助你有一个列表,比如:

print(rows)
# [
#     {"operation": "op1", "label": "label1", "query": "query1"},
#     {"operation": "op1", "label": "label1", "query": "query2"},
#     {"operation": "op1", "label": "label2", "query": "query3"},
#     {"operation": "op2", "label": "label3", "query": "query4"},
#     {"operation": "op2", "label": "label4", "query": "query5"},
#     {"operation": "op2", "label": "label3", "query": "query6"},
# ]


使用输入行(dicts)列表,迭代并直接创建JSON结构,然后打开输出文件并转储它:

data = []
for row in rows:
    obj = {
        "operation": row["operation"],
        "topic": {
            "label": row["label"],
            "query": row["query"],
        },
    }

    data.append(obj)

with open("output.json", "w", encoding="utf-8") as f:
    json.dump(data, f, indent=4)


考虑到我上面分享的输入CSV,我得到:

[
    {
        "operation": "op1",
        "topic": { "label": "label1", "query": "query1" }
    },
    {
        "operation": "op1",
        "topic": { "label": "label1", "query": "query2" }
    },
    {
        "operation": "op1",
        "topic": { "label": "label2", "query": "query3" }
    },
    {
        "operation": "op2",
        "topic": { "label": "label3", "query": "query4" }
    },
    {
        "operation": "op2",
        "topic": { "label": "label4", "query": "query5" }
    },
    {
        "operation": "op2",
        "topic": { "label": "label3", "query": "query6" }
    }
]


我只看到你需要groupby,如果你想在最终的JSON中将类似的对象分组在一个公共键下,比如:

{
    "op1@@label1": [
        {
            "operation": "op1",
            "topic": { "label": "label1", "query": "query1" }
        },
        {
            "operation": "op1",
            "topic": { "label": "label1", "query": "query2" }
        }
    ],
    "op1@@label2": [
        {
            "operation": "op1",
            "topic": { "label": "label2", "query": "query3" }
        }
    ],
    "op2@@label3": [
        {
            "operation": "op2",
            "topic": { "label": "label3", "query": "query4" }
        },
        {
            "operation": "op2",
            "topic": { "label": "label3", "query": "query6" }
        }
    ],
    "op2@@label4": [
        {
            "operation": "op2",
            "topic": { "label": "label4", "query": "query5" }
        }
    ]
}


要做到这一点,我建议首先定义一个 *key函数 *(就像你的lambda一样,但现在定义了其他函数):

def key_func(row):
    return (row["operation"], row["label"])


现在,按照文档,在分组之前对行进行排序:

rows.sort(key=key_func)
grouped_iter = groupby(rows, key=key_func)


我将数据重新定义为对象/dict。每个分组键都有一个我们之前创建的对象的数组/列表。然后,在grouped_iter上迭代:

data = {}
for key, grouped_rows in grouped_iter:
    grouped_list = []
    for row in grouped_rows:
        obj = {
            "operation": row["operation"],
            "topic": {
                "label": row["label"],
                "query": row["query"],
            },
        }

        grouped_list.append(obj)

    data["@@".join(key)] = grouped_list


然后打开输出JSON文件并转储,如上所述。
您可以查看输入CSV和输出JSONs here的完整代码。

相关问题