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出力を同じようにしたいです。問題は、すべてを1つの巨大な長い行にダンプすることです。

私は次のようなものを使用しfor line in csvfile:て、reader = csv.DictReader( line, fieldnames)各行をループするコードの下でコードを実行しようとしましたが、ファイル全体を1行で実行し、ファイル全体を別の行でループします...行がなくなるまで続行します。

これを修正するための提案はありますか?

編集:明確にするために、現在私は持っています:(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 2013年

回答:


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
しかし、問題は
出力ファイルが

1
@MONTYHS:この回答の最初の文は、outfileがjsonドキュメントではないことを説明しています。代わりにそれは何ですか。この質問をした人とは別の問題がありますか?
SingleNegationElimination 2014年

6
@ abhi1610:入力にヘッダーが必要な場合はDictReaderfieldnames引数を指定せずにを構築する必要があります。次に、最初の行を読み取り、ファイルからフィールド名を取得します。
SingleNegationElimination

1
そして、あなたのファイルのエンコーディングを追加するために良いですcsvfile = open('file.csv', 'r',encoding='utf-8') し、 jsonfile = open('file.json', 'w',encoding='utf-8')
マレクBernád

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の応答を取得して、パイプラインで使用できる3つのライナーに簡略化しました。

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.dumpにopenで使用できることにも注意してくださいjsonfile

json.dump(data, jsonfile)

私が探しているものではありません。元の質問を編集して、目的の出力を明確にして示しました。ヒントをありがとうございます。これは後で役立つかもしれません。
BeanBagKing 2013年

2

これは古いのですが、SingleNegationEliminationのコードが必要でしたが、utf-8以外の文字を含むデータに問題がありました。これらは私があまり気にしていない分野に現れたので、無視することにしました。しかし、それはいくつかの努力を要しました。私はpythonを初めて使用するので、試行錯誤を繰り返して動作しました。コードは、utf-8の追加処理を含むSingleNegationEliminationのコピーです。私は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に変換する最も簡単な方法の1つです。


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年

主なエラーは、このコードがheaders引数をに渡さないことが原因である可能性が高いためDictReader、入力ファイルの最初の行からフィールド名を推測しています: "FirstName、lastname、"ではなくJohn、Doe、5、 "None"など...
SingleNegationElimination 2013年

より良いオプション、これは実際にCSVを解析して、目的のフィールドを
探し

私はというエラーを取得するTypeError: expected string or buffer
CodyBugstein
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.