如何将CSV文件转换为多行JSON?

119

这是我的代码,非常简单的东西...

import csv
import json

csvfile = open('file.csv', 'r')
jsonfile = open('file.json', 'w')

fieldnames = ("FirstName","LastName","IDNumber","Message")
reader = csv.DictReader( csvfile, fieldnames)
out = json.dumps( [ row for row in reader ] )
jsonfile.write(out)

声明一些字段名称,读者使用 CSV 读取文件,并使用字段名称将文件转储为 JSON 格式。以下是问题...

CSV 文件中的每个记录都在不同的行上。我希望 JSON 输出也是这样。问题是它把所有内容都倾倒在一行上。

我尝试过像 for line in csvfile: 这样的代码,然后在它下面运行我的代码,如 reader = csv.DictReader(line, fieldnames),它会循环遍历每一行,但是它会在一个巨大的长行上处理整个文件,然后再在另一行上循环遍历整个文件...直到没有行为止。

有什么建议可以纠正这个问题吗?

编辑:为了澄清,目前我有:

[{"FirstName":"John","LastName":"Doe","IDNumber":"123","Message":"None"},{"FirstName":"George","LastName":"Washington","IDNumber":"001","Message":"Something"}]

我要找的是:(2个记录,分别放在2行)

{"FirstName":"John","LastName":"Doe","IDNumber":"123","Message":"None"}
{"FirstName":"George","LastName":"Washington","IDNumber":"001","Message":"Something"}

不是每个字段都要缩进或单独成行,而是每个记录都要单独成行。

一些示例输入。

"John","Doe","001","Message1"
"George","Washington","002","Message2"

1
我不确定你的代码是否完全符合你所说的,它应该生成[{..row..},{..row..},...]而不是{..row..}{..row..}..。也就是说,输出看起来将是一个JSON对象数组,而不是一系列不相关的JSON对象。 - SingleNegationElimination
12个回答

176
您期望的输出存在问题,因为它不是有效的 JSON 文档;它是一个 JSON 文档流!如果这正是您需要的,那么就没有问题。但这意味着,对于您想要输出的每个文档,您都需要调用“json.dumps”。由于您想要分隔文档的换行符不包含在这些文档中,所以您需要自己提供它。因此,我们只需要将循环从“json.dump”的调用中提取出来,并为写入的每个文档插入换行符即可。
import csv
import json

csvfile = open('file.csv', 'r')
jsonfile = open('file.json', 'w')

fieldnames = ("FirstName","LastName","IDNumber","Message")
reader = csv.DictReader( csvfile, fieldnames)
for row in reader:
    json.dump(row, jsonfile)
    jsonfile.write('\n')

1
太好了!很抱歉你不得不进行一些心灵读取来理解它,感谢您的更正/澄清。这正是我所寻找的。 - BeanBagKing
4
问题是输出文件不是有效的 JSON 格式。 - MONTYHS
1
@MONTYHS:这个答案的第一句话解释了outfile不是一个json文档,以及它实际上是什么。你是否遇到了与提问者不同的问题? - SingleNegationElimination
@SingleNegationElimination 但是,在输出的 json 文件中,如果存在 csv 的头部信息,它也会包含在内。有什么方法可以将其删除? - abhi1610
6
如果你期望输入中包含一个标题行,那么构造 DictReader 时不需要指定 fieldnames 参数;它会自动读取文件中的第一行并将其用作字段名。 - SingleNegationElimination
2
最好为您的文件添加编码csvfile = open('file.csv', 'r',encoding='utf-8')jsonfile = open('file.json', 'w',encoding='utf-8') - Marek Bernád

40
你可以使用Pandas DataFrame来实现这一点,以下是示例:
import pandas as pd
csv_file = pd.DataFrame(pd.read_csv("path/to/file.csv", sep = ",", header = 0, index_col = False))
csv_file.to_json("/path/to/new/file.json", orient = "records", date_format = "epoch", double_precision = 10, force_ascii = True, date_unit = "ms", default_handler = None)

很简洁,完成了任务。 - Akhil

16
import csv
import json

file = 'csv_file_name.csv'
json_file = 'output_file_name.json'

#Read CSV File
def read_CSV(file, json_file):
    csv_rows = []
    with open(file) as csvfile:
        reader = csv.DictReader(csvfile)
        field = reader.fieldnames
        for row in reader:
            csv_rows.extend([{field[i]:row[field[i]] for i in range(len(field))}])
        convert_write_json(csv_rows, json_file)

#Convert csv data into json
def convert_write_json(data, json_file):
    with open(json_file, "w") as f:
        f.write(json.dumps(data, sort_keys=False, indent=4, separators=(',', ': '))) #for pretty
        f.write(json.dumps(data))


read_CSV(file,json_file)

json.dumps()的文档


1
正确的答案,以我个人看来。 - JohnnyFromBF
1
你必须选择以下这行代码:f.write(json.dumps(data, sort_keys=False, indent=4, separators=(',', ': '))) #for pretty 或者这行代码:f.write(json.dumps(data)) - 不能同时存在! - S. A.
完美运行,返回一个JSON数组。 - Akhil

12

我采用了@SingleNegationElimination的回答,并将其简化为三行代码,可以在管道中使用:

我采用了@SingleNegationElimination的回答,并将其简化为三行代码,可以在管道中使用:

import csv
import json
import sys

for row in csv.DictReader(sys.stdin):
    json.dump(row, sys.stdout)
    sys.stdout.write('\n')

1
有人还记得可怕的 Perl 单行代码吗?python -c 'import json;import csv;out=open("jsonfilename","w");c=csv.DictReader(open("csvfilename"));[(json.dump(x,out),out.write("\n")) for x in c]' - John

7
你可以尝试这个
import csvmapper

# how does the object look
mapper = csvmapper.DictMapper([ 
  [ 
     { 'name' : 'FirstName'},
     { 'name' : 'LastName' },
     { 'name' : 'IDNumber', 'type':'int' },
     { 'name' : 'Messages' }
  ]
 ])

# parser instance
parser = csvmapper.CSVParser('sample.csv', mapper)
# conversion service
converter = csvmapper.JSONConverter(parser)

print converter.doConvert(pretty=True)

编辑:

更简单的方法

import csvmapper

fields = ('FirstName', 'LastName', 'IDNumber', 'Messages')
parser = CSVParser('sample.csv', csvmapper.FieldMapper(fields))

converter = csvmapper.JSONConverter(parser)

print converter.doConvert(pretty=True)

4
我认为你应该至少明确提到你正在使用第三方模块“csvmapper”来完成这个任务(也许还要说明在哪里获取它),而不是使用内置的功能。 - martineau

4

我知道这篇文章已经老旧了,但我需要SingleNegationElimination代码中的一部分内容,但是我的数据中存在非UTF-8字符,出现在我不太关心的字段中,所以我选择忽略它们。然而,这需要一些努力。我刚开始学Python,经过一些尝试和错误之后,我让它能够运行了。这段代码是SingleNegationElimination的复制,额外处理了utf-8。我试图用https://docs.python.org/2.7/library/csv.html来完成,但最终放弃了。以下代码可以正常工作。

import csv, json

csvfile = open('file.csv', 'r')
jsonfile = open('file.json', 'w')

fieldnames = ("Scope","Comment","OOS Code","In RMF","Code","Status","Name","Sub Code","CAT","LOB","Description","Owner","Manager","Platform Owner")
reader = csv.DictReader(csvfile , fieldnames)

code = ''
for row in reader:
    try:
        print('+' + row['Code'])
        for key in row:
            row[key] = row[key].decode('utf-8', 'ignore').encode('utf-8')      
        json.dump(row, jsonfile)
        jsonfile.write('\n')
    except:
        print('-' + row['Code'])
        raise

3
使用 pandas 和 json 库:
import pandas as pd
import json
filepath = "inputfile.csv"
output_path = "outputfile.json"

df = pd.read_csv(filepath)

# Create a multiline json
json_list = json.loads(df.to_json(orient = "records"))

with open(output_path, 'w') as f:
    for item in json_list:
        f.write("%s\n" % item)

3
indent参数添加到json.dumps中。
 data = {'this': ['has', 'some', 'things'],
         'in': {'it': 'with', 'some': 'more'}}
 print(json.dumps(data, indent=4))

此外,请注意,您可以简单地使用带有打开的 jsonfile 的 json.dump:
json.dump(data, jsonfile)

不太符合我的要求。我编辑了原来的问题以澄清并展示所需的输出。谢谢你的提示,这可能会在以后派上用场。 - BeanBagKing

2
如何使用Pandas将csv文件读入DataFrame(pd.read_csv),然后如果需要,操作列(删除或更新值),最后将DataFrame转换回JSON(pd.DataFrame.to_json)。
注意:我没有检查这种方法的效率如何,但这绝对是操作和转换大型csv到json的最简单方法之一。

0
def read():
    noOfElem = 200  # no of data you want to import
    csv_file_name = "hashtag_donaldtrump.csv"  # csv file name
    json_file_name = "hashtag_donaldtrump.json"  # json file name

    with open(csv_file_name, mode='r') as csv_file:
        csv_reader = csv.DictReader(csv_file)
        with open(json_file_name, 'w') as json_file:
            i = 0
            json_file.write("[")
            
            for row in csv_reader:
                i = i + 1
                if i == noOfElem:
                    json_file.write("]")
                    return

                json_file.write(json.dumps(row))

                if i != noOfElem - 1:
                    json_file.write(",")

修改上述三个参数,一切就都完成了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接