Type error : list indices must be integers or slices, not dict

Type error : list indices must be integers or slices, not dict

我正在尝试读取 json 数据并写入 csv 文件但无法正常工作。如何处理它以获得我的预期输出

代码:

import json
import csv 
import ast


# Using json loads to load data from varaible which holds json data 
jdata = json.loads(data)

# Fetching all headers from json and converting into list   
jkey = list(jdata[0].keys())  

# get length 
glen_count = len(data)


# Looping through the keys to write data to csv file  
for r in range(glen_count):
  for hd in jkey:
    with open("/content/sample_data/abc.csv",'w') as wr:
      csv_wr = csv.DictWriter(wr,fieldnames=jkey)
      csv_wr.writeheader()
      csv_wr.writerows(jdata[jdata[r][hd]])  # error : Type error : list indices must be integers or slices, not dict

我的变量data包含json

data = '''
[

 {
  "_id": {
    "$oid": "5fc7897969b8ab14e1cad8f4"
  },
  "m": "24:6F:28:55:7C:55",
  "t": "o",
  "pId": {
    "$oid": "5fc7894ff7fa2b262ecb6c46"
  },
  "pVal": {
    "title": "Switch",
    "val": 1,
    "status": null,
    "portType": "AC",
    "portIcon": "AC",
    "_id": "5fc7894ff7fa2b262ecb6c46",
    "no": "0",
    "cat": "s",
    "device": {
      "ports": [
        "5fc7894ff7fa2b262ecb6c46"
      ],
      "_id": "5fc7894ff7fa2b262ecb6c45",
      "macId": "24:6F:28:55:7C:55",
      "deviceId": "LTAC21220050009",
      "dType": "5ee38d3a4afdf74cf8b07dfb",
      "createdAt": "2020-12-02T12:32:15.235Z",
      "updatedAt": "2020-12-02T12:32:36.773Z",
      "__v": 0,
      "assignedTo": "5fc62223f7fa2b262ecb6c2d"
    },
    "mac": "24:6F:28:55:7C:55",
    "__v": 0,
    "createdAt": "2020-12-02T12:32:15.237Z",
    "updatedAt": "2020-12-02T12:32:57.776Z"
  },
  "dId": {
    "$oid": "5fc7894ff7fa2b262ecb6c45"
  },
  "createdAt": {
    "$date": "2020-12-02T12:32:57.781Z"
  },
  "updatedAt": {
    "$date": "2020-12-02T12:32:57.781Z"
  },
  "__v": 0
},{
  "_id": {
    "$oid": "5fc7897b69b8ab14e1cad8f5"
  },
  "m": "24:6F:28:55:7C:55",
  "t": "o",
  "pId": {
    "$oid": "5fc7894ff7fa2b262ecb6c46"
  },
  "pVal": {
    "title": "Switch",
    "val": 0,
    "status": null,
    "portType": "AC",
    "portIcon": "AC",
    "_id": "5fc7894ff7fa2b262ecb6c46",
    "no": "0",
    "cat": "s",
    "device": {
      "ports": [
        "5fc7894ff7fa2b262ecb6c46"
      ],
      "_id": "5fc7894ff7fa2b262ecb6c45",
      "macId": "24:6F:28:55:7C:55",
      "deviceId": "LTAC21220050009",
      "dType": "5ee38d3a4afdf74cf8b07dfb",
      "createdAt": "2020-12-02T12:32:15.235Z",
      "updatedAt": "2020-12-02T12:32:36.773Z",
      "__v": 0,
      "assignedTo": "5fc62223f7fa2b262ecb6c2d"
    },
    "mac": "24:6F:28:55:7C:55",
    "__v": 0,
    "createdAt": "2020-12-02T12:32:15.237Z",
    "updatedAt": "2020-12-02T12:32:59.951Z"
  },
  "dId": {
    "$oid": "5fc7894ff7fa2b262ecb6c45"
  },
  "createdAt": {
    "$date": "2020-12-02T12:32:59.955Z"
  },
  "updatedAt": {
    "$date": "2020-12-02T12:32:59.955Z"
  },
  "__v": 0
}

]

预期输出需要写入 csv 文件:列:id , val , createdAt , updatedAt

id , val , createdAt , updatedAt
5fc7897969b8ab14e1cad8f4 , 0 , 2020-12-02T12:32:57.781Z , 2020-12-02T12:32:57.781Z
5fc7897b69b8ab14e1cad8f5 , 0 , 2020-12-02T12:32:59.955Z , 2020-12-02T12:32:59.955Z

好的,有几件事:

  1. jkey = list(jdata[0].keys()) 会给你 jkeys = ['_id', 'm', 't', 'pId', 'pVal', 'dId', 'createdAt', 'updatedAt', '__v'],这比你想要的键多。如果您的目标是 select 只有 id , val , createdAt , updatedAtjkeys 必须反映为 jkeys = ['id' , 'val' , 'createdAt' , 'updatedAt']。毕竟,这是您传递给字段名的值。这些是 header 个名称,它标识了值的写入顺序。
  2. glen_count = len(data) 可能是一个错字,你打算写 jdata,data 是包含 json 数据的字符串,所以你会计算这个字符串的长度。
  3. 您遇到的错误是因为表达式 jdata[jdata[r][hd]] 的 return 是 {'$oid': '5fc7897969b8ab14e1cad8f4'},一个字典。您正在使用这个作为列表 jdata.
  4. 的索引
  5. 关于 DictWriterwriterows:您将特定的字段名传递给它的构造函数,在您的例子中,它是 jkeys = ['id' , 'val' , 'createdAt' , 'updatedAt']。这是您想要的 header。然后,您必须使用带有 writerows 的字典列表或带有 writerow 的单个字典。 Writerows 将让您一次写入所有实例,而 writerow 是一次写入一个实例。请参阅 CSV File Reading and Writing 作为参考。
  6. 小心循环 with open("/content/sample_data/abc.csv",'w') as wr:,您将重写自己的文件!请参阅 Reading and Writing Files 了解书写模式!

我将post以下作为解决方案,使用writerows将写入文件的逻辑和设置行的逻辑分开。希望这些是所需的 header。如果没有,根据自己的需要改也很容易。

import json
import csv 
import ast

jdata = json.loads(data)

# Only desired headers 
jkeys = ['id' , 'val' , 'createdAt' , 'updatedAt']

# setting up rows
list_rows = []
for el in jdata:
  dict_jdata = {}
  dict_jdata['id'] = el['_id']['$oid']
  dict_jdata['val'] = str(el['pVal']['val'])
  dict_jdata['createdAt'] = el['createdAt']['$date']
  dict_jdata['updatedAt'] = el['updatedAt']["$date"]
  list_rows.append(dict_jdata)

# Writing to a file  
with open("/content/sample_data/abc2.csv",'w') as wr:
  csv_wr = csv.DictWriter(wr,fieldnames=jkeys)
  csv_wr.writeheader()
  csv_wr.writerows(list_rows)

希望这对您有所帮助 :)