Caricamento e analisi di un file JSON con più oggetti JSON


101

Sto cercando di caricare e analizzare un file JSON in Python . Ma sono bloccato nel tentativo di caricare il file:

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

I rendimenti:

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

Ho guardato 18.2. json- Codificatore e decodificatore JSON nella documentazione di Python, ma è piuttosto scoraggiante leggere questa documentazione dall'aspetto orribile.

Prime righe (rese anonime con voci casuali):

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

Risposte:


222

Hai un file di testo in formato JSON Lines . Devi analizzare il tuo file riga per riga:

import json

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

Ogni riga contiene un JSON valido, ma nel suo insieme non è un valore JSON valido poiché non esiste un elenco di primo livello o una definizione di oggetto.

Si noti che poiché il file contiene JSON per riga, si risparmia il mal di testa di provare ad analizzarlo tutto in una volta sola o di capire un parser JSON in streaming. È ora possibile scegliere di elaborare ciascuna riga separatamente prima di passare alla successiva, risparmiando memoria nel processo. Probabilmente non vuoi aggiungere ogni risultato a un elenco e quindi elaborare tutto se il tuo file è davvero grande.

Se disponi di un file contenente singoli oggetti JSON con delimitatori intermedi, utilizza Come posso utilizzare il modulo "json" per leggere un oggetto JSON alla volta? per analizzare singoli oggetti utilizzando un metodo bufferizzato.


2
+1 Forse vale la pena notare che se non hai bisogno di tutti gli oggetti contemporaneamente, elaborarli uno per uno può essere un approccio più efficiente. In questo modo non sarà necessario memorizzare interi dati nella memoria, ma un singolo pezzo di essi.
Tadeck

1
@Pi_: avrai un dizionario, quindi accedi ai campi come chiavi:data = json.loads(line); print data[u'votes']
Martijn Pieters

1
@Pi_: stampa il risultato di json.loads () quindi o usa il debugger per ispezionare.
Martijn Pieters

1
@Pi_: no; non confondere il formato JSON con la rappresentazione dict di Python. Stai vedendo dizionari Python con stringhe ora.
Martijn Pieters

1
@ user2441441: vedi la risposta collegata dal post qui.
Martijn Pieters


4

Questo è mal formattato. Hai un oggetto JSON per riga, ma non sono contenuti in una struttura di dati più grande (cioè un array). Dovrai riformattarlo in modo che inizi [e termini ]con una virgola alla fine di ogni riga, oppure analizzalo riga per riga come dizionari separati.


20
Con un file da 50 MB, probabilmente l'OP è comunque meglio gestire i dati riga per riga. :-)
Martijn Pieters

11
Se il file è mal formattato dipende dal proprio punto di vista. Se doveva essere nel formato "linee JSON", è valido. Vedi: jsonlines.org
LS
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.