CSV dosyasını çok satırlı JSON'a nasıl dönüştürebilirim?


98

İşte kodum, gerçekten basit şeyler ...

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)

Bazı alan adlarını bildirin, okuyucu dosyayı okumak için CSV'yi ve dosyayı bir JSON formatına dökmek için dosyalanmış adları kullanır. İşte sorun ...

CSV dosyasındaki her kayıt farklı bir satırdadır. JSON çıktısının aynı şekilde olmasını istiyorum. Sorun şu ki, hepsini tek bir dev, uzun hat üzerine döküyor.

Benzeri bir şey kullanmayı denedim for line in csvfile:ve sonra kodumu reader = csv.DictReader( line, fieldnames)her satırda döngü yapan, ancak dosyanın tamamını bir satırda yapıyor, sonra tüm dosya boyunca başka bir satırda döngü yapıyor ... satırlar bitene kadar devam ediyor .

Bunu düzeltmek için herhangi bir öneriniz var mı?

Düzenleme: Açıklığa kavuşturmak için, şu anda var: (1. satırdaki her kayıt)

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

Ne arıyorum: (2 satırda 2 kayıt)

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

Her alan ayrı bir satırda girintili / girintili değil, ancak her kayıt kendi satırında.

Bazı örnek girdiler.

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

kodunuzun tam olarak söylediğinizi yaptığından emin değilim ; üretmesi gerektiğini [{..row..},{..row..},...]değil {..row..}{..row..}... Diğer bir deyişle, çıktı, bağlantısız json nesnelerinin bir akışı değil, json nesnelerinin bir json dizisi olacak gibi görünür.
SingleNegationElimination

Yanıtlar:


146

İstediğiniz çıktıyla ilgili sorun, bunun geçerli bir json belgesi olmamasıdır; bir json belgeleri akışı !

Sorun değil, eğer ihtiyacınız olan şey buysa, ancak bu, çıktınızda istediğiniz her belge için aramanız gerektiği anlamına gelir json.dumps.

Belgelerinizi ayırmak istediğiniz satırsonu bu belgelerde bulunmadığından, kendiniz sağlamak için kancaya sahipsiniz. Bu yüzden, json.dump çağrısından döngüyü çıkarmamız ve yazılan her belge için yeni satırları araya girmemiz gerekiyor.

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
Mükemmel! Özür dilerim, onu almak için biraz akıl okuması yapmanız gerekti ve düzeltmeler / açıklamalar için teşekkürler. Tam olarak aradığım buydu.
BeanBagKing

4
ancak sorun şu ki,
çıktı dosyası

1
@MONTYHS: Bu cevabın ilk cümlesi, outfile'ın bir json belgesi olmadığını açıklıyor; ve onun yerine ne olduğu. Bu soruyu soran kişiden farklı bir sorununuz mu var?
SingleNegationElimination

6
@ abhi1610: Eğer girdide bir başlık bekliyorsanız, DictReaderbir fieldnamesargüman vermeden oluşturmalısınız ; daha sonra alan adlarını dosyadan almak için ilk satırı okuyacaktır.
SingleNegationElimination

2
Ve dosyalarınız için kodlama eklemekte csvfile = open('file.csv', 'r',encoding='utf-8')jsonfile = open('file.json', 'w',encoding='utf-8')
fayda var

23

Bunu başarmak için Pandas DataFrame'i aşağıdaki Örneklerle kullanabilirsiniz:

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
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 belgeleri ()


Doğru cevap, imho.
JohnnyFromBF

9

@ SingleNegationElimination'ın yanıtını aldım ve bunu bir boru hattında kullanılabilecek üç satırlık bir hale getirdim:

import csv
import json
import sys

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

6

Deneyebilirsin bu

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)

Düzenle:

Daha basit yaklaşım

import csvmapper

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

converter = csvmapper.JSONConverter(parser)

print converter.doConvert(pretty=True)

3
Bence csvmapperyerleşik bir şeyin aksine, bunu yapmak için (ve belki de nereden alacağınızı) en azından açıkça üçüncü taraf bir modül kullandığınızı söylemelisiniz .
martineau

2

indentParametreyi şuraya ekleyin:json.dumps

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

Ayrıca json.dump, açıkken kullanabileceğinizi de unutmayın jsonfile:

json.dump(data, jsonfile)

Tam aradığım bu değil. İstenilen çıktıyı netleştirmek ve göstermek için orijinal sorumu düzenledim. Yine de ipucu için teşekkürler, bu daha sonra işe yarayabilir.
BeanBagKing

2

Bunun eski olduğunu görüyorum, ancak SingleNegationElimination'dan koda ihtiyacım vardı ancak utf-8 olmayan karakterler içeren verilerle sorun yaşadım. Bunlar, fazla ilgilenmediğim alanlarda ortaya çıktı, bu yüzden onları görmezden gelmeyi seçtim. Ancak bu biraz çaba gerektirdi. Python'da yeniyim, bu yüzden bazı deneme yanılma ile çalışmasını sağladım. Kod, utf-8'in ekstra işlemesine sahip SingleNegationElimination'ın bir kopyasıdır. Bunu https://docs.python.org/2.7/library/csv.html ile yapmaya çalıştım ama sonunda pes ettim . Aşağıdaki kod işe yaradı.

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

Pandalar'ı csv dosyasını bir DataFrame'e ( pd.read_csv ) okumak , ardından isterseniz sütunları değiştirmek (onları bırakmak veya değerleri güncellemek) ve son olarak DataFrame'i tekrar JSON'a ( pd.DataFrame.to_json ) dönüştürmek için kullanmaya ne dersiniz ?

Not: Bunun ne kadar verimli olacağını kontrol etmedim, ancak bu kesinlikle büyük bir csv'yi json'a dönüştürmenin ve değiştirmenin en kolay yollarından biridir.


0

@ MONTYHS cevabında küçük bir gelişme olarak, bir grup alan adı ile yineleme:

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)

Bunu kullanmaya çalıştığımda "KeyError: 'FirstName" "alıyorum. Anahtar eklenecek gibi görünmüyor. Burada tam olarak ne yapmaya çalıştığından emin değilim, ama Wayne ile aynı girinti = 4'ü kullandığınız için çıktının aradığımla eşleşeceğini sanmıyorum. Hangi çıktı beklemeliyim? Ne aradığımı açıklığa kavuşturmak için orijinal gönderimi düzenledim.
BeanBagKing

Temel hata büyük olasılıkla bu kodun bir üstbilgi bağımsız değişkenini iletmemesinden kaynaklanır DictReader, bu nedenle alan adlarını girdi dosyasının ilk satırından tahmin eder: "Ad, soyad" yerine John, Doe, 5, "Hiçbiri" ve bu yüzden ...
SingleNegationElimination

Daha iyi seçenek, bu aslında istenen alanlar için CSV'yi ayrıştırır (işaretli cevapta olduğu gibi sadece sırayla değil)
GarciadelCastillo

TypeError: expected string or buffer
Derken
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.