从扁平CSV创建嵌套JSON

3 投票
1 回答
6751 浏览
提问于 2025-04-17 05:18

我想从一个CSV文件创建一个四层嵌套的JSON,参考这个例子:

Region,Company,Department,Expense,Cost
Gondwanaland,Bobs Bits,Operations,nuts,332
Gondwanaland,Bobs Bits,Operations,bolts,254
Gondwanaland,Maureens Melons,Operations,nuts,123

在每一层,我希望能把费用加起来,并把这个总费用包含在输出的JSON中,放在合适的位置。

输出的JSON结构应该大概是这样的:

    {
          "id": "aUniqueIdentifier", 
          "name": "usually a nodes name", 
          "data": [
                {
                      "key": "some key", 
                      "value": "some value"
                }, 
                {
                      "key": "some other key", 
                      "value": "some other value"
                }
          ], 
          "children": [/* other nodes or empty */ ]
    }

(参考链接: http://blog.thejit.org/2008/04/27/feeding-json-tree-structures-to-the-jit/)

我在考虑用Python写一个递归函数,但到目前为止这个方法并没有什么成功……如果有人能给我一个简单快捷的解决方案,我会非常感激!

更新:逐渐放弃了总结费用的想法,因为我实在搞不定 :(。我现在还不是很会用Python!能生成格式正确的JSON就已经足够了,如果需要的话我可以稍后再填入数字。

我一直在阅读、搜索解决方案,过程中学到了很多,但还是没能从上面的CSV结构创建出我的嵌套JSON文件。网上一定有简单的解决方案吧?也许其他人用不同的搜索词找到了更好的结果???

1 个回答

8

这里有一些提示。

首先,用 csv.reader 把输入的数据解析成一个列表的列表:

>>> rows = list(csv.reader(source.splitlines()))

然后,遍历这个列表,建立你的字典,并总结成本。根据你想要创建的结构,构建的过程可能看起来像这样:

>>> summary = []
>>> for region, company, department, expense, cost in rows[1:]:
    summary.setdefault(*region, company, department), []).append((expense, cost))

最后,用 json.dump 把结果写出来:

>>> json.dump(summary, open('dest.json', 'wb'))

希望下面的递归函数能帮助你入门。它会根据输入数据构建一个树形结构。请注意你希望叶子节点的类型,我们把它称为“成本”。你需要对这个函数进行详细的修改,以构建出你想要的确切结构:

import csv, itertools, json

def cluster(rows):
    result = []
    for key, group in itertools.groupby(rows, key=lambda r: r[0]):
        group_rows = [row[1:] for row in group]
        if len(group_rows[0]) == 2:
            result.append({key: dict(group_rows)})
        else:
            result.append({key: cluster(group_rows)})
    return result

if __name__ == '__main__':
    s = '''\
Gondwanaland,Bobs Bits,Operations,nuts,332
Gondwanaland,Bobs Bits,Operations,bolts,254
Gondwanaland,Maureens Melons,Operations,nuts,123
'''
    rows = list(csv.reader(s.splitlines()))
    r = cluster(rows)
    print json.dumps(r, indent=4)

撰写回答