Laden und Parsen einer JSON-Datei mit mehreren JSON-Objekten

101

Ich versuche, eine JSON-Datei in Python zu laden und zu analysieren . Aber ich bin festgefahren, um die Datei zu laden:

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

Ausbeuten:

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

Ich habe mir 18.2 angesehen. json- JSON-Codierer und -Decodierer in der Python-Dokumentation, aber es ist ziemlich entmutigend, diese schrecklich aussehende Dokumentation durchzulesen.

Erste Zeilen (anonymisiert mit zufälligen Einträgen):

{"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_
quelle

Antworten:

222

Sie haben eine Textdatei im JSON Lines-Format . Sie müssen Ihre Datei Zeile für Zeile analysieren:

import json

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

Jede Zeile enthält gültigen JSON-Wert, ist jedoch insgesamt kein gültiger JSON-Wert, da keine Liste oder Objektdefinition der obersten Ebene vorhanden ist.

Da die Datei JSON pro Zeile enthält, ersparen Sie sich die Kopfschmerzen beim Versuch, alles auf einmal zu analysieren oder einen Streaming-JSON-Parser zu finden. Sie können jetzt jede Zeile einzeln verarbeiten, bevor Sie mit der nächsten fortfahren, um Speicherplatz zu sparen. Sie möchten wahrscheinlich nicht jedes Ergebnis an eine Liste anhängen und dann alles verarbeiten, wenn Ihre Datei wirklich groß ist.

Wenn Sie eine Datei haben, die einzelne JSON-Objekte mit dazwischen liegenden Trennzeichen enthält, verwenden Sie Wie verwende ich das Modul 'json', um jeweils ein JSON-Objekt einzulesen? einzelne Objekte mit einer gepufferten Methode zu analysieren.

Martijn Pieters
quelle
2
+1 Vielleicht ist es erwähnenswert, dass die Verarbeitung nacheinander effizienter sein kann, wenn Sie nicht alle Objekte gleichzeitig benötigen. Auf diese Weise müssen Sie nicht ganze Daten im Speicher speichern, sondern nur einen einzigen Teil davon.
Tadeck
1
@ Pi_: Sie haben ein Wörterbuch, also greifen Sie einfach als Schlüssel auf die Felder zu:data = json.loads(line); print data[u'votes']
Martijn Pieters
1
@Pi_: Drucken Sie dann das Ergebnis von json.loads () aus oder verwenden Sie den Debugger zur Überprüfung.
Martijn Pieters
1
@Pi_: nein; Verwechseln Sie das JSON-Format nicht mit der Python-Dikt-Darstellung. Sie sehen jetzt Python-Wörterbücher mit Zeichenfolgen.
Martijn Pieters
1
@ user2441441: siehe die verlinkte Antwort aus dem Beitrag hier.
Martijn Pieters
11

Für diejenigen, die über diese Frage stolpern: Die Python- jsonlinesBibliothek (viel jünger als diese Frage) behandelt Dateien elegant mit einem JSON-Dokument pro Zeile. siehe https://jsonlines.readthedocs.io/

Wouter Polsterlee
quelle
4

Das ist schlecht formatiert. Sie haben ein JSON-Objekt pro Zeile, diese sind jedoch nicht in einer größeren Datenstruktur (dh einem Array) enthalten. Sie müssen es entweder neu formatieren, sodass es mit einem Komma am Ende jeder Zeile beginnt [und ]mit einem Komma endet , oder es zeilenweise als separate Wörterbücher analysieren.

Daniel Roseman
quelle
20
Mit einer 50-MB-Datei ist das OP wahrscheinlich ohnehin besser dran, zeilenweise mit den Daten umzugehen. :-)
Martijn Pieters
11
Ob die Datei schlecht formatiert ist, hängt von der jeweiligen Sichtweise ab. Wenn es im Format "JSON-Zeilen" sein sollte, ist es gültig. Siehe: jsonlines.org
LS