Warum kann Python diese JSON-Daten nicht analysieren?

1439

Ich habe diesen JSON in einer Datei:

{
    "maps": [
        {
            "id": "blabla",
            "iscategorical": "0"
        },
        {
            "id": "blabla",
            "iscategorical": "0"
        }
    ],
    "masks": [
        "id": "valore"
    ],
    "om_points": "value",
    "parameters": [
        "id": "valore"
    ]
}

Ich habe dieses Skript geschrieben, um alle JSON-Daten zu drucken:

import json
from pprint import pprint

with open('data.json') as f:
    data = json.load(f)

pprint(data)

Dieses Programm löst jedoch eine Ausnahme aus:

Traceback (most recent call last):
  File "<pyshell#1>", line 5, in <module>
    data = json.load(f)
  File "/usr/lib/python3.5/json/__init__.py", line 319, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.5/json/decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.5/json/decoder.py", line 355, in raw_decode
    obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Expecting ',' delimiter: line 13 column 13 (char 213)

Wie kann ich den JSON analysieren und seine Werte extrahieren?

michele
quelle
@kederrac Aus dem angegebenen Grund: "Diese Frage wurde durch einen Tippfehler oder ein Problem verursacht, das nicht mehr reproduziert werden kann." Der JSON ist ungültig.
Rob
@kederrac Das Problem wird durch einen Verwendungsfehler verursacht, nicht weil es reproduziert werden kann.
Rob

Antworten:

2128

Ihre Daten haben kein gültiges JSON- Format. Sie haben, []wann Sie haben sollten {}:

  • []sind für JSON-Arrays, die listin Python aufgerufen werden
  • {}sind für JSON-Objekte, die dictin Python aufgerufen werden

So sollte Ihre JSON-Datei aussehen:

{
    "maps": [
        {
            "id": "blabla",
            "iscategorical": "0"
        },
        {
            "id": "blabla",
            "iscategorical": "0"
        }
    ],
    "masks": {
        "id": "valore"
    },
    "om_points": "value",
    "parameters": {
        "id": "valore"
    }
}

Dann können Sie Ihren Code verwenden:

import json
from pprint import pprint

with open('data.json') as f:
    data = json.load(f)

pprint(data)

Mit Daten können Sie jetzt auch folgende Werte finden:

data["maps"][0]["id"]
data["masks"]["id"]
data["om_points"]

Probieren Sie diese aus und sehen Sie, ob es Sinn macht.

Justin Peel
quelle
1
Ok, ich muss meinen Code kontrollieren, da diese JSON-Datei aus einem Java-Objekt generiert wird. Vielen Dank.
michele
5
Danke für die Lösung. Beim Drucken wird ein Unicode-Symbol angezeigt. (zB u'valore '). Wie kann man das verhindern?
Tagebuch Portfolio
6
Schön, aber Python fügt u'vor jedem Schlüssel ein hinzu. Irgendeine Idee warum?
CodyBugstein
7
Aus diesem Grund ist Ihr Text vom Typ Unicode und nicht vom String. Meistens ist es besser, Text in Unicode für deutsche Umlaute zu haben und Textergebnisse mit anderen Modulen / Programmen usw. zu teilen. Also bist du gut!
Michael P
2
Ich möchte eine Beobachtung machen, die hoffentlich hilfreich und definitiv ironisch ist. Ich finde, dass das pprint-Modul dem json-Modul für hübsch druckendes json unterlegen ist. Wenn Sie beide ausprobieren, werden Sie mir sicher zustimmen. Um meine JSON-Datenstrukturen anzuzeigen und zu debuggen, habe ich Folgendes ausgeführt: output = json.dumps (data_structure, indent = 2, sort_keys = True) print (output) Ich denke, Sie werden die Einrückungssteuerung, Sortierung und Intelligenz finden Zeilenumbruch in der dumps () -Methode nach Ihren Wünschen. Wenn ich falsch denke, lass es mich bitte wissen.
Larold
307

Du data.jsonsolltest so aussehen:

{
 "maps":[
         {"id":"blabla","iscategorical":"0"},
         {"id":"blabla","iscategorical":"0"}
        ],
"masks":
         {"id":"valore"},
"om_points":"value",
"parameters":
         {"id":"valore"}
}

Ihr Code sollte sein:

import json
from pprint import pprint

with open('data.json') as data_file:    
    data = json.load(data_file)
pprint(data)

Beachten Sie, dass dies nur in Python 2.6 und withhöher funktioniert, da dies von der Anweisung abhängt . In Python 2.5 from __future__ import with_statementfinden Sie in Python <= 2.4 die Antwort von Justin Peel , auf der diese Antwort basiert.

Sie können jetzt auch auf einzelne Werte wie diesen zugreifen:

data["maps"][0]["id"]  # will return 'blabla'
data["masks"]["id"]    # will return 'valore'
data["om_points"]      # will return 'value'
Bengt
quelle
7
Ich habe eine Gegenstimme dazu bekommen. Vielleicht war nicht klar, warum ich eine andere Antwort für notwendig hielt. Hinweis zur Kompatibilität der with-Anweisung hinzugefügt.
Bengt
Entschuldigung für das Rollback, aber der vorgeschlagene Code würde data_file openlänger als nötig gespeichert bleiben.
Bengt
Unter Bezugnahme auf die 2.6-Dokumentation ( docs.python.org/2.6/library/io.html ) wird die Datei beim Öffnen einer Datei im Kontext "mit" automatisch geschlossen.
Steve S.
1
@SteveS. Ja, aber nicht bevor der Kontext verlassen wird. Wenn pprintSie im withKontext stehen, bleibt das data_filelänger geöffnet.
Bengt
1
@GayanPathirage Sie greifen darauf zu wie data["om_points"], data["masks"]["id"]. Die Idee ist, dass Sie jede Ebene in einem Wörterbuch erreichen können, indem Sie die 'Schlüsselpfade' angeben. Wenn Sie eine KeyErrorAusnahme erhalten, bedeutet dies, dass der Schlüssel nicht im Pfad vorhanden ist. Achten Sie auf Tippfehler oder überprüfen Sie die Struktur Ihres Wörterbuchs.
Nuhman
71

Die Antwort von Justin Peel ist wirklich hilfreich, aber wenn Sie Python 3 verwenden, sollte das Lesen von JSON folgendermaßen erfolgen:

with open('data.json', encoding='utf-8') as data_file:
    data = json.loads(data_file.read())

Hinweis: Verwenden Sie json.loadsanstelle von json.load. Nimmt in Python 3 json.loadseinen Zeichenfolgenparameter an. json.loadNimmt einen dateiähnlichen Objektparameter. data_file.read()Gibt ein String-Objekt zurück.

Um ehrlich zu sein, denke ich nicht, dass es in den meisten Fällen ein Problem ist, alle JSON-Daten in den Speicher zu laden.

Geng Jiawen
quelle
10
Warum sollte json.loadzugunsten von .loadsPython 3 vermieden werden ?
Zearin
10
Die Seite, die Sie verlinkt haben, sagt nichts über das Vermeiden aus load.
Dan Hulme
28
Diese Antwort liest die gesamte Datei in den Speicher, wenn dies nicht erforderlich ist, und legt nahe, dass in Python 3 JSON-Dateien nicht träge gelesen werden können, was nicht wahr ist. Es tut mir leid, aber es ist eine klare Ablehnung.
Łukasz Rogalski
10
Diese Antwort ist nicht korrekt. Es gibt keinen Grund, json.load nicht mit einem Open File Handler in Python3 zu verwenden. Entschuldigen Sie die Ablehnung, aber es scheint nicht so, als würden Sie die obigen Kommentare sehr sorgfältig lesen.
Dusktreader
5
+1 Diese Antwort ist großartig! Vielen Dank dafür und ich bin weit davon entfernt, nach einer Funktion zu suchen, die Zeichenfolgen verwenden kann, da ich nur mit Zeichenfolgen und Netzwerkanforderungen arbeite, die keine Dateien sind!
Newpeople
54
data = []
with codecs.open('d:\output.txt','rU','utf-8') as f:
    for line in f:
       data.append(json.loads(line))
user1743724
quelle
8
Dies ist die richtige Lösung, wenn Sie mehrere JSON-Objekte in einer Datei haben. json.loadsdekodiert nicht mehrere JSON-Objekte. Andernfalls wird der Fehler "Zusätzliche Daten" angezeigt.
Yasin_alm
Dies ist die beste Antwort. Andernfalls wird der Fehler "Zusätzliche Daten" ausgegeben.
Earthx9
39
Wenn mehrere JSON-Objekte in einer Datei enthalten sind, ist die Datei selbst nicht gültig. Wenn Sie mehrere Objekte in eine JSON-Datei aufnehmen möchten, sollten diese in einem Array auf der obersten Ebene der Datei enthalten sein.
Dusktreader
Wenn mehrere JSON-Objekte in einer Datei enthalten sind, handelt es sich bei der Datei nicht um ein einzelnes JSON-Objekt. Das ist irgendwie offensichtlich. Das Erstellen eines einzelnen Arrays aus den Objekten ist eine offensichtliche Problemumgehung. Aber JSON ist von Entwurf explizit beendet, bei fast jedem Niveau (von }, ]oder "). Daher können Sie tatsächlich mehrere Objekte in einer einzelnen Zeichenfolge oder Datei ohne Mehrdeutigkeit verketten. Das Problem hierbei ist, dass ein Parser, der ein einzelnes Objekt erwartet, fehlschlägt, wenn mehr als ein Objekt übergeben wird.
MSalters
Anzeige, die mehrere JSON-Objekte in einer einzigen Datei speichert: Dafür gibt es einen "Standard" - jsonlines.org/examples in .jsonl(json lines). Die Objekte werden durch ein Zeilenumbruchzeichen getrennt, wodurch die Vorverarbeitung für das Parsen trivial wird und ermöglicht um Dateien einfach zu teilen / zu stapeln, ohne sich um Start- / Endmarkierungen sorgen zu müssen.
Sebi
13

"Ultra JSON" oder einfach "ujson" kann die []Eingabe in Ihre JSON-Datei verarbeiten. Wenn Sie eine JSON-Eingabedatei als Liste von JSON-Elementen in Ihr Programm einlesen; wie [{[{}]}, {}, [], etc...]kann ujson beliebige Reihenfolge der Listen von Wörterbuch, Wörterbücher von Listen handhaben .

Sie finden ujson im Python- Paketindex und die API ist fast identisch mit der in Python integrierten jsonBibliothek.

ujson ist auch viel schneller, wenn Sie größere JSON-Dateien laden. Sie können die Leistungsdetails im Vergleich zu anderen Python-JSON-Bibliotheken unter demselben Link anzeigen.

Moeabdol
quelle
9

Wenn Sie Python3 verwenden, können Sie versuchen, Ihren ( connection.jsonDatei-) JSON in Folgendes zu ändern :

{
  "connection1": {
    "DSN": "con1",
    "UID": "abc",
    "PWD": "1234",
    "connection_string_python":"test1"
  }
  ,
  "connection2": {
    "DSN": "con2",
    "UID": "def",
    "PWD": "1234"
  }
}

Verwenden Sie dann den folgenden Code:

connection_file = open('connection.json', 'r')
conn_string = json.load(connection_file)
conn_string['connection1']['connection_string_python'])
connection_file.close()
>>> test1
Sushmit
quelle
1
Dies funktioniert auch in 2.7.5
Siddardha
17
Dadurch bleibt das Dateihandle geöffnet. eine withAussage zu verwenden wäre besser
Corey Goldberg
6

Hier geht es mit geänderter data.jsonDatei:

{
    "maps": [
        {
            "id": "blabla",
            "iscategorical": "0"
        },
        {
            "id": "blabla",
            "iscategorical": "0"
        }
    ],
    "masks": [{
        "id": "valore"
    }],
    "om_points": "value",
    "parameters": [{
        "id": "valore"
    }]
}

Sie können Daten auf der Konsole aufrufen oder drucken, indem Sie die folgenden Zeilen verwenden:

import json
from pprint import pprint
with open('data.json') as data_file:
    data_item = json.load(data_file)
pprint(data_item)

Erwartete Ausgabe für print(data_item['parameters'][0]['id']):

{'maps': [{'id': 'blabla', 'iscategorical': '0'},
          {'id': 'blabla', 'iscategorical': '0'}],
 'masks': [{'id': 'valore'}],
 'om_points': 'value',
 'parameters': [{'id': 'valore'}]}

Erwartete Ausgabe für print(data_item['parameters'][0]['id']):

valore
JoboFive
quelle
Wenn wir eine Spalte hinzufügen möchten, um zu zählen, wie viele Beobachtungen "Karten" haben, wie könnten wir diese Funktion schreiben?
Chenxi
5

Bei dieser Analyse gibt es zwei Arten.

  1. Analysieren von Daten aus einer Datei aus einem Systempfad
  2. Analysieren von JSON von einer Remote-URL.

Aus einer Datei können Sie Folgendes verwenden

import json
json = json.loads(open('/path/to/file.json').read())
value = json['key']
print json['value']

In diesem Artikel wird das vollständige Parsen und Abrufen von Werten anhand von zwei Szenarien erläutert. Analysieren von JSON mit Python

Bibin Wilson
quelle
4

Als python3 Benutzer ,

Der Unterschied zwischen loadund loadsMethoden ist besonders wichtig, wenn Sie JSON-Daten aus einer Datei lesen.

Wie in den Dokumenten angegeben:

json.load:

Deserialisieren Sie fp (eine .read () - unterstützende Textdatei oder Binärdatei, die ein JSON-Dokument enthält) mithilfe dieser Konvertierungstabelle in ein Python-Objekt.

json.loads:

json.loads: Deserialisieren Sie s (eine str-, bytes- oder bytearray-Instanz, die ein JSON-Dokument enthält) mithilfe dieser Konvertierungstabelle in ein Python-Objekt.

Die Methode json.load kann geöffnete JSON-Dokumente direkt lesen, da sie Binärdateien lesen kann.

with open('./recipes.json') as data:
  all_recipes = json.load(data)

Infolgedessen sind Ihre JSON-Daten in einem Format verfügbar, das gemäß dieser Konvertierungstabelle angegeben wurde:

https://docs.python.org/3.7/library/json.html#json-to-py-table

Muratgozel
quelle
Wie ist dies eine Antwort auf die gestellte Frage? Der Benutzer verwendete die richtige Methode zum Laden der JSON-Datei.
Raj006