【问题标题】:JSON to CSV in python convert issuepython转换问题中的JSON到CSV
【发布时间】:2023-03-19 16:46:01
【问题描述】:

我正在尝试将嵌套的 JSON 对象文件转换为 CSV。 这是 JSON 的示例

{
   "total_hosts" : [
      {
         "TYPE" : "AGENT",
         "COUNT" : 6
      }
   ],
   "installed" : [
      {
         "ID" : "admin-4.0",
         "VERSION" : 4,
         "ADDON_NAME" : "Administration"
      },
      {
         "ID" : "admin-2.0",
         "VERSION" : 2,
         "ADDON_NAME" : "Administration"
      },
      {
         "ID" : "ch-5.0",
         "VERSION" : "5",
         "ADDON_NAME" : "Control Host"
      }
   ],
   "virtual_machine" : [
      {
         "COUNT" : 4,
         "TYPE" : "VM"
      }

TYPE,COUNT,ID,VERSION 像这些是列,但问题不是每个对象都有值,有些对象有 1 个具有这些值的对象,或者有些对象更多,我写在行中,所以我试图写空白该列没有值时的空格。

将其写入 CSV 的代码

json_input = open('all.json')
try:
    decoded = json.load(json_input)
# tell computer where to put CSV
    outfile_path='Path to CSV'
# open it up, the w means we will write to it
    writer = csv.writer(open(outfile_path,'w'))


       for index in range(len(decoded['installed'])):
            row = []

            if decoded['total_hosts'][index]['TYPE'] is None:
                row.append(str(''))
            else:
                row.append(str(decoded['total_hosts'][index]['TYPE']))
            if decoded['total_hosts'][index]['COUNT'] is None:
                row.append(str(''))
            else:
                row.append(str(decoded['total_hosts'][index]['COUNT']))

            writer.writerow(row)

我收到Index out of range 错误,我什至尝试了True/False if 的条件。

谁能帮我解决这个问题?

更新:预期输出:

TYPE,COUNT,ID,VERSION,ADDON_NAME,COUNT,TYPE
AGENT,6,admin-4.0,4,Administration,4,VM
 , ,admin-2.0,2,Administration, , 
 , ,cd-5.0,5,Control Host, , 

所以基本上,当该列没有值时,我需要空格。

问题已修改:输出:

AGENT,6,,,
 , ,admin-4.0,4,Administration
 , ,admin-2.0,2,Administration
 , ,ch-5.0,5,Control Host

预期输出:

AGENT,6,admin-4.0,4,Administration
 , ,admin-2.0,2,Administration
 , ,ch-5.0,5,Control Host

更新:我什至尝试过

            row.append(str(entry.get('TYPE', '')))
            row.append(str(entry.get('COUNT', '')))
            row.append(str(entry.get('ID', '')))
            row.append(str(entry.get('VERSION', '')))
            row.append(str(entry.get('ADDON_NAME', '')))
            writer.writerow(row)

仍然得到与上面相同的输出。 :(

【问题讨论】:

  • 您的installedtotal_hosts 列表的长度不同;您正在循环 range(len(decoded['installed'])),然后使用 decoded['total_hosts']decoded['_hosts'] 列表中的索引(后者可能是一个错字)。
  • 您应该包含输入和预期输出的完整示例。
  • 是的,它是错字 :) 实际上我想为文件中的所有元素循环它,但由于它们是单独的对象/数组,所以我采用最大数量元素的数组并循环它,并且这就是为什么我设置 IF 条件,所以如果没有值,它应该附加空格。所以我可以维护列结构。
  • @user3520135:是decoded['total_hosts'][index] 操作引发了异常,没有尝试访问['TYPE'](这会引发KeyError 异常)。

标签: python arrays json object csv


【解决方案1】:

这里有两个错误:

  1. 您使用decoded['installed'] 的长度生成索引,然后用于decoded['total_hosts'] 列表。这将产生索引错误,因为decoded['total_hosts'] 没有那么多条目。

  2. 访问不存在的密钥会抛出KeyError;请改用dict.get() method 来检索值或默认值。

在列表上直接循环要简单得多,不需要生成索引:

for host in decoded['total_hosts']:
    row = [host.get('TYPE', ''), host.get('COUNT', '')]
    writer.writerow(row)

你可以扩展它来处理多个键:

for key in ('total_hosts', 'installed', 'virtual_machine'):
    for entry in decoded[key]:
        row = [entry.get('TYPE', ''), entry.get('COUNT', '')]
        writer.writerow(row)

如果您需要合并两个条目的输出,请使用itertools.izip_longest() 将列表配对,当较短的列表用完时使用默认值:

from itertools import izip_longest

for t, i, v in izip_longest(decoded['total_hosts'], decoded['installed'], decoded['version'], fillvalue={}):
    row = [t.get('TYPE', ''), t.get('COUNT', ''), 
           i('ID', ''), i('VERSION', ''), i.get('ADDON_NAME', ''),
           v.get('COUNT', ''), v.get('TYPE', '')]
    writer.writerow(row)

这允许三个列表中的任何一个都比其他列表短。

对于 2.6 之前的 Python 版本(添加了 itertools.izip_longest),您必须假设 installed 总是最长的,然后使用:

for i, installed in decoded['installed']:
    t = decoded['types'][i] if i < len(decoded['types']) else {}
    v = decoded['version'][i] if i < len(decoded['version']) else {}
    row = [t.get('TYPE', ''), t.get('COUNT', ''), 
           installed['ID'], installed['VERSION'], installed['ADDON_NAME'],
           v.get('COUNT', ''), v.get('TYPE', '')]
    writer.writerow(row)

【讨论】:

  • @user3520135:该错误通常表明您忘记了前一行的结束 )]
  • @user3520135:注意,row = [] 行完全是多余的。
  • 是的,你是对的,再次感谢,但有一个小问题。
  • @user3520135:您没有指定要合并 total_hostsinstalled 列表;如果有多个total_hosts 条目会怎样?
  • 抱歉,我正在尝试以列、行格式输出,所以如果有更多的值,它将被写入相应的列,如果没有,则会有空格。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-04
  • 2021-05-24
  • 1970-01-01
  • 1970-01-01
  • 2017-08-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多