複数のJSONオブジェクトを含むJSONファイルの読み込みと解析


101

Pythonで JSONファイルを読み込んで解析しようとしています。しかし、私はファイルをロードしようとして立ち往生しています:

import json
json_data = open('file')
data = json.load(json_data)

収量:

ValueError: Extra data: line 2 column 1 - line 225116 column 1 (char 232 - 160128774)

18.2jsonを見ました PythonドキュメントのJSONエンコーダーとデコーダー。ただし、この恐ろしいドキュメントを一読するのはかなり意外です。

最初の数行(ランダムなエントリで匿名化):

{"votes": {"funny": 2, "useful": 5, "cool": 1}, "user_id": "harveydennis", "name": "Jasmine Graham", "url": "http://example.org/user_details?userid=harveydennis", "average_stars": 3.5, "review_count": 12, "type": "user"}
{"votes": {"funny": 1, "useful": 2, "cool": 4}, "user_id": "njohnson", "name": "Zachary Ballard", "url": "https://www.example.com/user_details?userid=njohnson", "average_stars": 3.5, "review_count": 12, "type": "user"}
{"votes": {"funny": 1, "useful": 0, "cool": 4}, "user_id": "david06", "name": "Jonathan George", "url": "https://example.com/user_details?userid=david06", "average_stars": 3.5, "review_count": 12, "type": "user"}
{"votes": {"funny": 6, "useful": 5, "cool": 0}, "user_id": "santiagoerika", "name": "Amanda Taylor", "url": "https://www.example.com/user_details?userid=santiagoerika", "average_stars": 3.5, "review_count": 12, "type": "user"}
{"votes": {"funny": 1, "useful": 8, "cool": 2}, "user_id": "rodriguezdennis", "name": "Jennifer Roach", "url": "http://www.example.com/user_details?userid=rodriguezdennis", "average_stars": 3.5, "review_count": 12, "type": "user"}

回答:


222

あなたは持っているJSON行形式のテキストファイルを。ファイルを1行ずつ解析する必要があります。

import json

data = []
with open('file') as f:
    for line in f:
        data.append(json.loads(line))

ラインには、有効なJSONが含まれていますが、何もトップレベルのリストまたはオブジェクト定義が存在しないよう全体として、それが有効なJSON値ではありません。

ファイルには1行ごとにJSONが含まれているため、一度にすべてを解析したり、ストリーミングJSONパーサーを理解したりするという煩わしさから解放されます。各行を個別に処理してから次の行に進むことができるようになり、プロセスのメモリを節約できます。各結果を1つのリストに追加して、ファイルが本当に大きい場合はすべて処理したくない場合があります。

区切り文字が間にある個別のJSONオブジェクトを含むファイルがある場合、「json」モジュールを使用して一度に1つのJSONオブジェクトを読み取るにはどうすればよいですか?バッファリングされたメソッドを使用して個々のオブジェクトを解析します。


2
+1一度にすべてのオブジェクトが必要ない場合は、オブジェクトを1つずつ処理する方が効率的なアプローチかもしれません。この方法では、データ全体をメモリに格納する必要はありませんが、その一部をメモリに格納する必要があります。
Tadeck 2012

1
@Pi_:あなたはとてもだけでキーとしてフィールドにアクセスする、辞書を持っています:data = json.loads(line); print data[u'votes']
マルタインピータース

1
@Pi_:json.loads()の結果を出力するか、デバッガーを使用して検査します。
Martijn Pieters

1
@Pi_:いいえ。JSON形式とPython dict表現を混同しないでください。現在、文字列を含むpython辞書が表示されています。
Martijn Pieters

1
@ user2441441:こちらの投稿からリンクされた回答をご覧ください。
Martijn Pieters


4

これフォーマット正しくありません。1行に1つのJSONオブジェクトがありますが、より大きなデータ構造(配列)には含まれていません。各行の終わりにカンマで始まり、コンマで[終わるように再フォーマットするか]、個別の辞書として行ごとに解析する必要があります。


20
50MBのファイルの場合、OPはおそらくデータを1行ずつ処理する方がよいでしょう。:-)
Martijn Pieters

11
ファイルの形式が正しくないかどうかは、自分の視点に依存します。「JSON lines」形式であることが意図されていた場合、それは有効です。参照:jsonlines.org
LS
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.