Como converter o arquivo CSV para JSON multi-linha? [duplicado]

Esta pergunta já tem uma resposta:
  • A descarregar múltiplas variáveis para o disco em Json. Uma variável por linha 1 resposta
Aqui está o meu código, coisas muito simples...

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)

Declare alguns nomes de Campos, o leitor usa CSV para ler o arquivo, e os nomes arquivados para enviar o arquivo para um formato JSON. Aqui está o ... problema...

Cada registo no ficheiro CSV está numa linha diferente. Quero que a saída do JSON seja igual. O problema é que despeja tudo numa fila gigante e comprida.

tentei usar algo como for line in csvfile: e depois executar o meu código abaixo com reader = csv.DictReader( line, fieldnames) que passa por cada linha, mas faz todo o ficheiro numa linha, depois passa por todo o ficheiro noutra linha... continua até ficar sem linhas.

Todas as sugestões de correcção isto?

Editar: para clarificar, de momento tenho: (todos os registos na linha 1)

[{"FirstName":"John","LastName":"Doe","IDNumber":"123","Message":"None"},{"FirstName":"George","LastName":"Washington","IDNumber":"001","Message":"Something"}]
O que procuro: (2 registos em 2 linhas)

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

não cada campo individual indentado/numa linha separada, mas cada registo na sua própria linha.

alguns dados de amostra.

"John","Doe","001","Message1"
"George","Washington","002","Message2"
Author: martineau, 2013-10-31

10 answers

O problema com a sua saída desejada é que não é um documento JSON válido,; é um fluxo de documentos json !

Tudo bem, se é o que precisas, mas isso significa que para cada documento que queres na tua saída, terás de ligar json.dumps.

Uma vez que a linha nova que quer separar os seus documentos não está contida nesses documentos, está em risco de ser você a fornecê-la. Então, só precisamos de tirar o loop da chamada para o json.dump e interpose linhas novas para cada documento escrito.
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')
 89
Author: SingleNegationElimination, 2013-10-31 12:49:43

Eu peguei na resposta da eliminação de uma única negação e simplifiquei-a para uma linha de três linhas que pode ser usada num oleoduto:

import csv
import json
import sys

for row in csv.DictReader(sys.stdin):
    json.dump(row, sys.stdout)
    sys.stdout.write('\n')
 6
Author: Lawrence I. Siden, 2015-11-25 22:25:17
Pode tentar isto.
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)

Editar:

Abordagem mais simples

import csvmapper

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

converter = csvmapper.JSONConverter(parser)

print converter.doConvert(pretty=True)
 6
Author: Snork S, 2016-08-23 14:57:43

Pode usar o DataFrame Pandas para atingir este objectivo, com o seguinte exemplo:

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)
 3
Author: Naufal, 2017-02-02 12:13:15

Adicione o parâmetro indent Ao json.dumps

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

Também pode usar json.dump com a abertura jsonfile:

json.dump(data, jsonfile)
 2
Author: Wayne Werner, 2013-10-31 03:19:43
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)

Documentação do json.dumps()

 2
Author: Laxman, 2018-01-06 19:58:46

Que tal usar Pandas para ler o ficheiro csv num DataFrame (pd.read_ CSV ), manipulando depois as colunas se quiser (largando-as ou actualizando os valores) e convertendo finalmente o nome de dados de volta para JSON ( pd. DataFrame. to_ JSON).

Nota: ainda não verifiquei a eficiência disto, mas esta é definitivamente uma das formas mais fáceis de manipular e converter um grande csv para json.

 1
Author: impiyush, 2016-07-07 17:10:20
Vejo que isto é antigo, mas precisava do Código da eliminação de uma única geração, mas tinha problemas com os dados que não continham caracteres utf-8. Estes apareceram em campos que eu não estava excessivamente preocupado com Então eu escolhi ignorá-los. No entanto, isso exigiu algum esforço. Sou novo no python por isso, com alguma tentativa e erro, consegui que funcionasse. O código é uma cópia da eliminação Deegação única com o tratamento extra de utf-8. Tentei fazê-lo com https://docs.python.org/2.7/library/csv.html mas em o fim desistiu. O código abaixo funcionou.
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
Author: Mark Channing, 2016-08-18 15:50:42

Como ligeira melhoria para a resposta de @MONTYHS, iterando através de um tup de nomes de campo:

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)
 0
Author: GarciadelCastillo, 2014-03-05 19:43:35
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)
 -1
Author: MONTYHS, 2013-10-31 12:03:05