2013-10-22 66 views
9

當我在Python 3使用json.loads和捕捉任何導致的錯誤,如:如何從json.loads得到錯誤的位置在Python

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

我得到這樣一個有用的信息:

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

我想能夠顯示這個給用戶,以及正是導致問題的位置(我正在閱讀用戶編寫的JSON)。我如何擺脫線條和欄目?

我可以在err上使用正則表達式,但這感覺像個壞主意,因爲我不知道這條消息是否國際化,並且可能會在不同版本的python中進行更改。有沒有更好的辦法?

回答

8

掃描json/decoder.py source code,我們可以看到,解碼器的錯誤信息使用errmsg函數構造:

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) 

由於這是一個純Python模塊,可以很容易地包裝這個函數的自定義一個。這個過程被稱爲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) 

顯然,這種解決方案並不理想,因爲實現可能隨時更改,但它仍然不是依賴於消息更好。在修補之前,您應該檢查errmsg是否存在(並且可能如果沒有其他參數或使用可變參數)。

+0

這非常有趣,但我認爲我更願意將字符串正則表達式,因爲如果我的正則表達式在未來的版本中未能匹配,我總是可以做其他事情,但是這可能(在我看來)導致一些非常可怕的副作用。 但是,這也仍然回答問題爲'不',並且讓我查找我可以找回的所有格式的消息。謝謝! –

+0

我認爲這將是更好,如果json解析器返回一個更合適的異常,其中包含這些字段。我爲它打開了一個[issue](http://bugs.python.org/issue19361)。 –

0

如果json對象很小,在這裏過去你的Json對象 http://jsonlint.com/ 它給出了json斷點的位置。

+1

我想在程序中使用它,而該網站是有幫助的,我不想開始在我的代碼中調用它! –

3

如果使用simplejson庫,你會得到具有良好資質的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) 

    """ 

希望,這將是merged into stdlib很快。