2013-10-22 5 views
9

bekommen, wenn ich json.loads in Python 3 und fangen alle daraus resultierenden Fehler zu verwenden, wie:Wie Fehlerstelle von json.loads in Python

try: 
    data = json.loads(string) 
except ValueError as err: 
    print(err) 

ich eine hilfreiche Nachricht wie erhalten:

Expecting ',' delimiter: line 12 column 12 (char 271) 

Ich würde gerne in der Lage sein, dies dem Benutzer anzuzeigen, zusammen mit genau der Stelle, die das Problem verursacht (ich lese in benutzerdefinierten JSON). Wie kann ich die Zeile und die Spalte heraus bekommen?

Ich könnte eine Regex auf Fehler verwenden, aber das fühlt sich wie eine schlechte Idee, wie ich nicht weiß, ob diese Nachricht internationalisiert ist, und konnte in verschiedenen Versionen von Python ändern. Gibt es einen besseren Weg?

Antwort

8

die json/decoder.py source code Scannen, können wir sehen, dass die Fehlermeldungen des Decoders aufgebaut werden unter Verwendung der errmsg Funktion:

def errmsg(msg, doc, pos, end=None): 
    # Note that this function is called from _json 
    lineno, colno = linecol(doc, pos) 
    if end is None: 
     fmt = '{0}: line {1} column {2} (char {3})' 
     return fmt.format(msg, lineno, colno, pos) 
     #fmt = '%s: line %d column %d (char %d)' 
     #return fmt % (msg, lineno, colno, pos) 
    endlineno, endcolno = linecol(doc, end) 
    fmt = '{0}: line {1} column {2} - line {3} column {4} (char {5} - {6})' 
    return fmt.format(msg, lineno, colno, endlineno, endcolno, pos, end) 
    #fmt = '%s: line %d column %d - line %d column %d (char %d - %d)' 
    #return fmt % (msg, lineno, colno, endlineno, endcolno, pos, end) 

Da dies ein reines Python-Modul ist, ist es einfach, diese Funktion mit einem benutzerdefinierten einem wickeln. Dieser Prozess ist bekannt als monkey patching:

import json 

original_errmsg= json.decoder.errmsg 

def our_errmsg(msg, doc, pos, end=None): 
    json.last_error_position= json.decoder.linecol(doc, pos) 
    return original_errmsg(msg, doc, pos, end) 

json.decoder.errmsg= our_errmsg 

try: 
    data = json.loads('{1:}') 
except ValueError as e: 
    print("error at", json.last_error_position) 

Offensichtlich ist diese Lösung nicht ideal, da die Implementierung jederzeit ändern kann, obwohl es immer noch besser ist als die Botschaft zu verlassen. Sie sollten überprüfen, ob vor dem Patchen vorhanden ist (und möglicherweise, wenn keine anderen Argumente vorhanden sind, oder varargs verwenden).

+0

Dies ist sehr interessant, aber ich denke, ich würde es vorziehen, die Zeichenfolge neu zu bestimmen, wie ich immer etwas anderes tun kann, wenn meine Regex in einer zukünftigen Version nicht übereinstimmt, aber dies könnte (zu mir scheint) zu einigen führen wirklich schreckliche Nebenwirkungen. Allerdings beantwortet dies auch immer noch die Frage als "nein", und lassen Sie mich auch alle Formate der Nachricht nachschlagen, die ich zurückbekommen könnte. Vielen Dank! –

+0

Ich denke, es wäre schöner, wenn der JSON-Parser eine besser qualifizierte Exception zurückgeben würde, die diese Felder enthält. Ich habe ein [Problem] (http://bugs.python.org/issue19361) dafür geöffnet. –

0

wenn json Objekt klein ist, Past Ihre Json Objekt hier http://jsonlint.com/ es gibt, wo json bricht.

+1

Ich möchte dies in einem Programm verwenden, während diese Website hilfreich ist, würde ich nicht anfangen, es in meinem Code zu nennen! –

3

Wenn Sie simplejson Bibliothek verwenden, erhalten Sie einen gut qualifizierten JSONDecodeError:

class JSONDecodeError(ValueError): 
    """Subclass of ValueError with the following additional properties: 

    msg: The unformatted error message 
    doc: The JSON document being parsed 
    pos: The start index of doc where parsing failed 
    end: The end index of doc where parsing failed (may be None) 
    lineno: The line corresponding to pos 
    colno: The column corresponding to pos 
    endlineno: The line corresponding to end (may be None) 
    endcolno: The column corresponding to end (may be None) 

    """ 

Hoffentlich diese merged into stdlib bald sein wird.

Verwandte Themen