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


98

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

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)该代码循环遍历每一行,但它在一行上执行整个文件,然后在另一行上遍历整个文件...继续直到行数结束。

有任何纠正建议吗?

编辑:澄清一下,目前我有:(第1行的每条记录)

[{"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"

我不确定您的代码是否完全符合您的要求;它应该产生[{..row..},{..row..},...]{..row..}{..row..}..。也就是说,输出看起来将是json对象的json数组,而不是未连接的json对象的流。
SingleNegationElimination

Answers:


143

您所需输出的问题是它不是有效的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 2013年

4
但问题是outfile不是有效的json
MONTYHS 2014年

1
@MONTYHS:这个答案的第一句话解释说outfile不是json文档;以及它是什么。您和提出这个问题的人有不同的问题吗?
SingleNegationElimination 2014年

6
@ abhi1610:如果期望输入中包含标头,则应在DictReader不提供fieldnames参数的情况下构造;然后它将读取第一行以从文件中获取字段名称。
SingleNegationElimination

1
最好为文件添加编码,csvfile = open('file.csv', 'r',encoding='utf-8') 并且 jsonfile = open('file.json', 'w',encoding='utf-8')
MarekBernád18年

21

您可以通过以下示例使用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)

10

我接受了@SingleNegationElimination的响应,并将其简化为可以在管道中使用的三层:

import csv
import json
import sys

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

8
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()的文档


6

你可以试试这个

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)

3
我认为您至少应该明确提到您正在使用第三方模块csvmapper来执行此操作(以及在何处获取它),而不是内置的内容。
martineau

2

indent参数添加到json.dumps

 data = {'this': ['has', 'some', 'things'],
         'in': {'it': 'with', 'some': 'more'}}
 print(json.dumps(data, indent=4))

另请注意,您可以简单地使用json.dumpopen jsonfile

json.dump(data, jsonfile)

并不是我要找的东西。我编辑了原始问题,以阐明并显示所需的输出。不过,感谢您的提示,稍后可能会派上用场。
BeanBagKing 2013年

2

我看到这很旧,但是我需要来自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

1

如何使用Pandas将csv文件读入DataFrame(pd.read_csv),然后根据需要操纵列(删除它们或更新值),最后将DataFrame转换回JSON(pd.DataFrame.to_json)。

注意:我还没有检查过效率如何,但这绝对是处理大型csv并将其转换为json的最简单方法之一。


0

作为@MONTYHS答案的略微改进,通过一堆字段名进行迭代:

import csv
import json

csvfilename = 'filename.csv'
jsonfilename = csvfilename.split('.')[0] + '.json'
csvfile = open(csvfilename, 'r')
jsonfile = open(jsonfilename, 'w')
reader = csv.DictReader(csvfile)

fieldnames = ('FirstName', 'LastName', 'IDNumber', 'Message')

output = []

for each in reader:
  row = {}
  for field in fieldnames:
    row[field] = each[field]
output.append(row)

json.dump(output, jsonfile, indent=2, sort_keys=True)

-1
import csv
import json
csvfile = csv.DictReader('filename.csv', 'r'))
output =[]
for each in csvfile:
    row ={}
    row['FirstName'] = each['FirstName']
    row['LastName']  = each['LastName']
    row['IDNumber']  = each ['IDNumber']
    row['Message']   = each['Message']
    output.append(row)
json.dump(output,open('filename.json','w'),indent=4,sort_keys=False)

当我尝试使用它时,我得到“ KeyError:'FirstName'”。似乎没有添加密钥。我不确定您要在这里做什么,但是我不认为输出与我要找的东西匹配,因为您使用与Wayne相同的indent = 4。我应该期待什么输出?我编辑了我的原始帖子,以澄清我在寻找什么。
BeanBagKing 2013年

关键错误很可能是因为此代码未将标头参数传递给DictReader,所以它从输入文件的第一行猜测字段名称:John,Doe,5,“ None”而不是“ FirstName,lastname”和等等...
SingleNegationElimination

更好的选择,这实际上是解析所需字段的CSV(不仅仅是按顺序排列,如标记的答案中所示)
GarciadelCastillo 2014年

TypeError: expected string or buffer
说错了
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.