我有一个 .json 文件,其中包含如下所示的对象:
[
{
"a": "0.038",
"b": "1",
"c": "0"
},
{
"a": "0.040",
"b": "1",
"c": "0"
},
...
]
我有一个.csv文件,如下所示:
d e f
0.00 0.00 0.00
0.02 -0.08 -0.08
0.04 -0.32 -0.32
...
我想修改 .json 文件以从.csv文件添加新的键/值对,但我不想只是在文件末尾附加新项目,而是将.csv中的一行添加到每个元素的末尾。所以新的 .json 看起来像这样:
[
{
"a": "0.038",
"b": "1",
"c": "0",
"d": "0.00",
"e": "0.00",
"f": "0.00"
},
{
"a": "0.040",
"b": "1",
"c": "0",
"d": "0.02",
"e": "-0.08",
"f": "-0.08""
},
...
]
我尝试了不同的方法(例如使用 append() 或 update()),但它们要么将.csv数据添加到 .json 文件的完整末尾,要么尝试将整个.csv数据添加到 .json 中第一个元素的末尾。在我看来,我需要做的是从 json 对象创建一个字典,将 csv 数据也加载到字典中,遍历每个 json 元素,然后将 csv 数据中的一行添加到其中,创建一个新的 json 对象。但是我没有得到我想要的输出,或者我遇到了无法附加到字典的问题。这是我现有的代码:
import csv
import json
def csv_to_json(csvFilePath, jsonFilePath):
with open("existing.json") as json_file:
data = json.load(json_file)
json_file.close() # Close the JSON file
#read csv file
with open(csvFilePath, encoding='utf-8') as csvf:
#load csv file data using csv library's dictionary reader
csvReader = csv.DictReader(csvf)
for item in data:
#convert each csv row into python dict
for row in csvReader:
#add this python dict to json array
item.update(row)
#convert python jsonArray to JSON string and write to file
with open(jsonFilePath, 'w', encoding='utf-8') as jsonf:
jsonString = json.dumps(data, indent = 4)
jsonf.write(jsonString)
#decide the 2 file paths according to your file system
csvFilePath = r'C:Users\Downloadsfilename.csv'
jsonFilePath = r'C:Users\Desktopfilename.json'
csv_to_json(csvFilePath, jsonFilePath)
您的问题是您有嵌套循环。这会产生几个问题:
for item in data:
#convert each csv row into python dict
for row in csvReader:
#add this python dict to json array
item.update(row)
csvReader = csv.DictReader(csvf)
使csvReader
成为一个迭代器。一旦你在for item in data
第一次迭代结束时读完所有csvReader
行,该迭代器就会耗尽,不会再产生任何行。因此,对于data
中的后续item
,您将永远不会csvReader
有任何行。您可以通过执行csvReader = list(csv.DictReader(...))
来解决此问题,这会将所有行读取到一个列表中,您可以迭代任意次数。- 修复此问题后,您可以使用
csvReader
的所有行更新data
中的每个item
。这不是您想要的,因为您只希望使用第i
行更新第i
item
。
要解决此问题,您需要zip()
两个迭代器,以便同时迭代data
和csvReader
:
for item, row in zip(data, csvReader):
item.update(row)
请注意,由于在这种情况下您不会多次迭代csvReader
,因此它不需要是一个列表,并且您的原始定义csvReader = csv.DictReader(csvf)
就足够了(您可能需要csvReader = csv.DictReader(csvf, delimiter="t")
来指定分隔符,默认情况下假定它是逗号)
现在你有data =
[{'a': '0.038', 'b': '1', 'c': '0', 'd': '0.00', 'e': '0.00', 'f': '0.00'},
{'a': '0.040', 'b': '1', 'c': '0', 'd': '0.02', 'e': '-0.08', 'f': '-0.08'}]
使用zip
将两个列表压缩在一起并合并字典:
>>> json_data = [
... {
... "a": "0.038",
... "b": "1",
... "c": "0"
... },
... {
... "a": "0.040",
... "b": "1",
... "c": "0"
... },
... ]
>>>
>>> csv_data = [
... {
... "d": "0.00",
... "e": "0.00",
... "f": "0.00"
... },
... {
... "d": "0.02",
... "e": "-0.08",
... "f": "-0.08"
... }
... ]
>>> from pprint import pprint
>>> pprint([j | c for j, c in zip(json_data, csv_data)])
[{'a': '0.038', 'b': '1', 'c': '0', 'd': '0.00', 'e': '0.00', 'f': '0.00'},
{'a': '0.040', 'b': '1', 'c': '0', 'd': '0.02', 'e': '-0.08', 'f': '-0.08'}]
在此处将2 个词典合并到一个表达式中。 前提是两个词典列表的长度相同:
list1 = [
{
"a": "0.038",
"b": "1",
"c": "0"
},
{
"a": "0.040",
"b": "1",
"c": "0"
}
]
list2 = [
{
"d": "0.00",
"e": "0.00",
"f": "0.00"
},
{
"d": "0.02",
"e": "-0.08",
"f": "-0.08"
}]
然后遍历任何列表的长度:
>>> result = [{**list1[i], **list2[i]} for i in range(len(list1))]
>>> result
[{'a': '0.038', 'b': '1', 'c': '0', 'd': '0.00', 'e': '0.00', 'f': '0.00'}, {'a': '0.040', 'b': '1', 'c': '0', 'd': '0.02', 'e': '-0.08', 'f': '-0.08'}]