Behandeln Sie den JSON-Dekodierungsfehler, wenn nichts zurückgegeben wird

78

Ich analysiere JSON-Daten. Ich habe kein Problem mit dem Parsen und verwende das simplejsonModul. Einige API-Anfragen geben jedoch einen leeren Wert zurück. Hier ist mein Beispiel:

{
"all" : {
    "count" : 0,
    "questions" : [     ]
    }
}

Dies ist das Segment meines Codes, in dem ich das JSON-Objekt analysiere:

 qByUser = byUsrUrlObj.read()
 qUserData = json.loads(qByUser).decode('utf-8')
 questionSubjs = qUserData["all"]["questions"]

Wie ich für einige Anfragen erwähnt habe, erhalte ich den folgenden Fehler:

Traceback (most recent call last):
  File "YahooQueryData.py", line 164, in <module>
    qUserData = json.loads(qByUser)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/simplejson/__init__.py", line 385, in loads
    return _default_decoder.decode(s)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/simplejson/decoder.py", line 402, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/simplejson/decoder.py", line 420, in raw_decode
    raise JSONDecodeError("No JSON object could be decoded", s, idx)
simplejson.decoder.JSONDecodeError: No JSON object could be decoded: line 1 column 0 (char 0)

Was wäre der beste Weg, um diesen Fehler zu behandeln?

Add-Semikolons
quelle
3
Was ist eigentlich Ihre Frage?
Tadeck
Du hast die Fragen beantwortet;) Sieht so aus, als würde ich die Frage einreichen, bevor ich die Frage wirklich schreibe. Danke für die Antwort.
Add-Semikolons
2
Ok, ich bin froh, dass ich geholfen habe - es sieht jetzt aus wie eine Telepathie;) Danke, dass du die Frage aufgenommen hast. Viel Glück!
Tadeck

Antworten:

150

In der Python-Programmierung gibt es eine Regel namens "Es ist einfacher, um Vergebung zu bitten als um Erlaubnis" (kurz: EAFP). Dies bedeutet, dass Sie Ausnahmen abfangen sollten, anstatt die Werte auf Gültigkeit zu überprüfen.

Versuchen Sie daher Folgendes:

try:
    qByUser = byUsrUrlObj.read()
    qUserData = json.loads(qByUser).decode('utf-8')
    questionSubjs = qUserData["all"]["questions"]
except ValueError:  # includes simplejson.decoder.JSONDecodeError
    print 'Decoding JSON has failed'

EDIT : Da simplejson.decoder.JSONDecodeErrortatsächlich von ValueError( Beweis hier ) erbt , habe ich die catch-Anweisung durch einfaches Verwenden vereinfacht ValueError.

Tadeck
quelle
11
Sie sollten immer die richtige Ausnahme abfangen. Andernfalls fehlt möglicherweise ein Fehler im Code, wenn eine tatsächliche ValueErrorAusnahme vorliegt oder eine andere Ausnahme, von der ebenfalls geerbt wird ValueError.
Julie in Austin
2
@ JulieinAustin: Das Problem ist, dass Sie in diesem Fall wirklich keine große Auswahl haben - das json-Modul von stdlib löst ValueError aus.
Tadeck
2
Dann würde ich mich von diesem Decoder fernhalten. Die ursprüngliche Frage betraf das simplejsonModul und wirft JSONDecodeErrorbei schlechten Eingaben sehr viel auf. Siehe Ihren früheren Link.
Julie in Austin
3
@ JulieinAustin: Ich würde es anders machen, da es eigentlich ... Standardbibliothek ist. Wenn Sie sich nicht zu sehr um die Geschwindigkeit sorgen , würde ich das verwenden, was bereits verfügbar ist. Ja, simplejsontut dies feinkörniger, aber es hat seine eigenen Probleme. Was würden Sie sagen, wenn der try...exceptBlock nur einen json.loadsAnruf kapseln würde ? Ich denke, das wäre dann besser, würde aber einen Kesselplatz erfordern, um die Anforderungen zu erfüllen (z. B. die Klasse der Ausnahme in etwas Feinkörnigeres zu ändern, aber wir sollten nicht versuchen, die Welt hier zu retten).
Tadeck
3
ValueErrorist zu weit gefasst, um in diesem Zusammenhang verwendet zu werden. In Bezug auf Benutzercode qUserData["all"]["questions"]könnte ValueErrorich auch werfen . Geschweige denn ein ValueErrorWesen, das anderswo im Inneren aufgewachsen ist simplejson. Dies ist die Art von Dingen, die Sie 6 Monate später wirklich hart beißen könnten, wenn die Dinge "ohne Grund" zu brechen beginnen
Anthony Manning-Franklin
10

Wenn Sie nichts dagegen nicht das Import - jsonModul, dann ist die beste Art und Weise zu handhaben ist durch json.JSONDecodeError(oder json.decoder.JSONDecodeErrorwie sie die gleichen sind) als mit den Standardfehler wie ValueErrorkönnten auch andere Ausnahmen fangen nicht notwendigerweise auf die json dekodieren eine verbunden.

from json.decoder import JSONDecodeError


try:
    qByUser = byUsrUrlObj.read()
    qUserData = json.loads(qByUser).decode('utf-8')
    questionSubjs = qUserData["all"]["questions"]
except JSONDecodeError as e:
    # do whatever you want

// BEARBEITEN (Okt 2020):

Wie @Jacob Lee im Kommentar erwähnt, könnte es die grundlegende gemeinsame sein TypeErrorangehoben , wenn das JSON - Objekt nicht ist str, bytesoder bytearray. Ihre Frage ist ungefähr JSONDecodeError, aber dennoch ist es wert, hier als Anmerkung erwähnt zu werden; Um auch diese Situation zu bewältigen, aber zwischen verschiedenen Problemen zu unterscheiden, könnte Folgendes verwendet werden:

from json.decoder import JSONDecodeError


try:
    qByUser = byUsrUrlObj.read()
    qUserData = json.loads(qByUser).decode('utf-8')
    questionSubjs = qUserData["all"]["questions"]
except JSONDecodeError as e:
    # do whatever you want
except TypeError as e:
    # do whatever you want in this case
pesekon2
quelle
Leider löst json.loads einen TypeError aus, wenn das JSON-Objekt kein str, bytes oder bytearray ist. Dies hat mich kürzlich gebissen, weil ich gedacht hatte, dass JSONDecodeError diese Umstände handhabt, z. B. wenn das Argument für json.loads am Ende None lautet.
Jacob Lee
1
@ JacobLee: Danke. Die ursprüngliche Frage ist, wie man am besten damit umgeht, JSONDecodeErroralso habe ich mich nur auf diese konzentriert, aber Sie haben Recht, und dieser Fall ist definitiv erwähnenswert. Ich habe es in die Antwort aufgenommen.
pesekon2