【问题标题】:Convert JSON to CSV when file has different keys using Python?当文件使用Python具有不同的键时将JSON转换为CSV?
【发布时间】:2016-08-23 00:41:52
【问题描述】:

我正在尝试将许多 JSON 文件写入 CSV 文件。每个 JSON 文件都有几个键,但不同的文件有不同的键。这里以三个 JSON 文件为例。

文件 A:

{"a": 1, "c": 2}

文件 B:

{"b": 5, "d": 3}

文件 C:

{"a": 6, "b": 7}

我想要一个这样的 CSV 文件,它有四列三行(为简单起见,省略了逗号):

a b c d

1   2 

  5   3

6 7 

执行此操作的一种方法是使用 csv 编写器通过多个 try/except 语句。但这变得不可行,因为我正在处理大量密钥。有其他选择吗?

【问题讨论】:

  • 这看起来并不像 CSV,使用空格作为分隔符和“空白空间”会使加载该数据变得非常困难。你也提前知道所有可能的键吗?
  • 你应该显示你拥有的代码。

标签: python json csv


【解决方案1】:

假设您提前知道所有可能的字段名称 csv.DictWriter 已经为此提供了解决方案,请在构造函数中使用 restval 参数:

如果读取的行的字段少于字段名序列,则 其余键采用可选restval 参数的值。

因此指定csv.DictWriter(..., restval=" ") 将用一个空格替换任何缺失值,尽管默认情况下restval 设置为""(一个空字符串),无论如何这可能对您更有用。

所以基本上你的代码应该是这样的:

import csv, json
all_fields = ["a","b","c","d"]
all_files = ["A.json","B.json","C.json"]

with open("OUTPUT.csv", "w") as output_file:
    writer = csv.DictWriter(output_file,all_fields)
    writer.writeheader()

    for filename in all_files:
        with open(filename,"r") as in_file:
            writer.writerow(json.load(in_file))

【讨论】:

    【解决方案2】:

    您可以将每个 JSON 文件附加到一个列表中,然后创建数据帧并连接。

    a = {"a": 1, "c": 2}
    b = {"b": 5, "d": 3}
    c = {"a": 6, "b": 7}
    data = [a, b, c]
    
    >>> pd.concat([pd.DataFrame(s, index=[0]) for s in data]).reset_index()
        a   b   c   d
    0   1 NaN   2 NaN
    1 NaN   5 NaN   3
    2   6   7 NaN NaN
    

    【讨论】:

      【解决方案3】:

      您可以使用缺少的键加载每个单独的字典并给它们空值。所以它可能看起来像这样

      for items in list:
          for x in ['a','b','c','d']:
              if x not in item:
                  item[x] = ""
      

      现在每个字典都有相同的键,你应该能够轻松地以你想要的格式编写 csv。

      【讨论】:

      • 1:这就是dict.setdefault 的用途,2:defaultdict 可以更有效地做到这一点。
      【解决方案4】:

      这行得通:

      csv_separator = ';'
      
      data = [{"a": 1, "c": 2},
      {"b": 5, "d": 3},
      {"a": 6, "b": 7}]
      
      headers = sorted(list(set(sum([list(l.keys()) for l in data], []))))
      
      with open('output.csv', 'w+') as f:
          f.write(csv_separator.join(headers))
          for l in data:
              line_elements = []
              for k in headers:
                  try:
                      line_elements.append(str(l[k]))
                  except: # key not in dict, append empty string, i'll let you catch the exception properly
                      line_elements.append('')
              f.write(csv_separator.join(line_elements))
      
      
      # Output : 
      # a;b;c;d
      # 1;;2;
      # ;5;;3
      # 6;7;;
      

      【讨论】:

      • 如果将所有内容都打印到标准输出,为什么还要打开文件?你也可以在dicts上使用.get方法来处理丢失的键。
      • 我忘记写入文件了,只是通过管道输出,感谢您的关注。
      猜你喜欢
      • 2021-10-29
      • 1970-01-01
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 2022-09-23
      • 1970-01-01
      • 1970-01-01
      • 2019-03-25
      相关资源
      最近更新 更多