Memuat dan mengurai file JSON dengan beberapa objek JSON

101

Saya mencoba memuat dan mengurai file JSON dengan Python . Tapi saya terjebak saat mencoba memuat file:

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

Hasil:

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

Saya melihat 18,2. json- Encoder dan decoder JSON dalam dokumentasi Python, tetapi cukup mengecewakan untuk membaca dokumentasi yang tampak mengerikan ini.

Beberapa baris pertama (dianonimkan dengan entri acak):

{"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"}
Pi_
sumber

Jawaban:

222

Anda memiliki file teks format Garis JSON . Anda perlu mengurai file Anda baris demi baris:

import json

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

Setiap baris berisi JSON yang valid, tetapi secara keseluruhan, ini bukan nilai JSON yang valid karena tidak ada daftar level teratas atau definisi objek.

Perhatikan bahwa karena file tersebut berisi JSON per baris, Anda tidak perlu pusing lagi mencoba mengurai semuanya sekaligus atau mencari tahu pengurai JSON streaming. Sekarang Anda dapat memilih untuk memproses setiap baris secara terpisah sebelum melanjutkan ke baris berikutnya, menghemat memori dalam prosesnya. Anda mungkin tidak ingin menambahkan setiap hasil ke satu daftar dan kemudian memproses semuanya jika file Anda sangat besar.

Jika Anda memiliki file yang berisi objek JSON individual dengan pemisah di antaranya, gunakan Bagaimana cara menggunakan modul 'json' untuk membaca di satu objek JSON pada satu waktu? untuk mengurai objek individu menggunakan metode buffer.

Martijn Pieters
sumber
2
+1 Mungkin perlu dicatat, bahwa jika Anda tidak membutuhkan semua objek sekaligus, memprosesnya satu per satu mungkin pendekatan yang lebih efisien. Dengan cara ini Anda tidak perlu menyimpan seluruh data di memori, tetapi hanya satu bagian saja.
Tadeck
1
@Pi_: Anda akan memiliki kamus, jadi cukup akses kolom sebagai kunci:data = json.loads(line); print data[u'votes']
Martijn Pieters
1
@Pi_: mencetak hasil dari json.loads () lalu atau gunakan debugger untuk memeriksa.
Martijn Pieters
1
@Pi_: tidak; jangan bingung antara format JSON dengan representasi python dict. Anda melihat kamus python dengan string sekarang.
Martijn Pieters
1
@ user2441441: lihat jawaban terkait dari posting di sini.
Martijn Pieters
11

bagi mereka yang tersandung pada pertanyaan ini: jsonlinespustaka python (jauh lebih muda dari pertanyaan ini) secara elegan menangani file dengan satu dokumen json per baris. lihat https://jsonlines.readthedocs.io/

guling wouter
sumber
4

Itu adalah sakit-diformat. Anda memiliki satu objek JSON per baris, tetapi objek tersebut tidak terdapat dalam struktur data yang lebih besar (yaitu, array). Anda juga perlu memformatnya sehingga dimulai dengan [dan diakhiri dengan ]koma di akhir setiap baris, atau parsing baris demi baris sebagai kamus terpisah.

Daniel Roseman
sumber
20
Dengan file 50MB, OP mungkin lebih baik menangani data baris demi baris. :-)
Martijn Pieters
11
Format file tidak tepat tergantung pada sudut pandang seseorang. Jika dimaksudkan dalam format "garis JSON", itu valid. Lihat: jsonlines.org
LS