"नहीं JSON ऑब्जेक्ट डिकोड किया जा सकता है" की तुलना में बेहतर त्रुटि संदेश प्रदर्शित करना


128

कुछ लंबे जटिल JSON फ़ाइल से डेटा लोड करने के लिए पायथन कोड:

with open(filename, "r") as f:
  data = json.loads(f.read())

(नोट: सबसे अच्छा कोड संस्करण होना चाहिए:

with open(filename, "r") as f:
  data = json.load(f)

लेकिन दोनों समान व्यवहार प्रदर्शित करते हैं)

JSON त्रुटि के कई प्रकारों के लिए (लापता सीमांकक, तार में गलत बैकस्लैश, आदि), यह एक अच्छा सहायक संदेश प्रिंट करता है जिसमें लाइन और कॉलम संख्या होती है जहां JSON त्रुटि पाई गई थी।

हालाँकि, JSON त्रुटि के अन्य प्रकारों के लिए (क्लासिक "एक सूची में अंतिम आइटम पर अल्पविराम का उपयोग करके", लेकिन यह भी सच / झूठ को बड़ा करने जैसी अन्य चीजें हैं), पायथन का आउटपुट सिर्फ:

Traceback (most recent call last):
  File "myfile.py", line 8, in myfunction
    config = json.loads(f.read())
  File "c:\python27\lib\json\__init__.py", line 326, in loads
    return _default_decoder.decode(s)
  File "c:\python27\lib\json\decoder.py", line 360, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "c:\python27\lib\json\decoder.py", line 378, in raw_decode
    raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded

उस प्रकार के ValueError के लिए, आपको यह बताने के लिए पायथन कैसे मिलता है कि JSON फ़ाइल में त्रुटि कहाँ है?


क्या आप अपनी फ़ाइल का एक अंश डंप कर सकते हैं?
केतुम

मैं अब किसी विशेष फ़ाइल में त्रुटि खोजने की कोशिश नहीं कर रहा हूँ; मैं अपने कार्यक्रम को संशोधित करने की कोशिश कर रहा हूं ताकि यह भविष्य में पढ़ने वाली किसी भी फ़ाइल में त्रुटि को उजागर करे।
OJW

2
सीधे तौर पर संबंधित नहीं, लेकिन आप json.load(f)इसके बजाय कर सकते हैंjson.loads(f.read())
मार्टिन सैमसन

@OJW इस व्यवहार पर अजगर का कौन सा संस्करण था?
jxramos

पायथन 3.8.1 अब एरर पोजिशन देता है "एक्सपेक्टिंग वैल्यू: लाइन 1 कॉलम 21 (
चार्ट

जवाबों:


173

मैंने पाया है कि simplejsonमॉड्यूल कई मामलों में अधिक वर्णनात्मक त्रुटियां देता है जहां अंतर्निहित jsonमॉड्यूल अस्पष्ट है। उदाहरण के लिए, किसी सूची में अंतिम आइटम के बाद अल्पविराम होने के मामले के लिए:

json.loads('[1,2,]')
....
ValueError: No JSON object could be decoded

जो बहुत वर्णनात्मक नहीं है। उसी ऑपरेशन के साथ simplejson:

simplejson.loads('[1,2,]')
...
simplejson.decoder.JSONDecodeError: Expecting object: line 1 column 5 (char 5)

काफी बेहतर! इसी तरह अन्य सामान्य त्रुटियों के लिए पूंजीकरण True


18
पायथन के भविष्य के संस्करणों में वे सुधार शामिल होंगे; यह एक ही परियोजना के नीचे है।
मार्टिन पीटर्स


1
@ user2016290 सीधे कोर / पैकेज फ़ाइलों का संपादन एक बुरा विचार है। अजगर बन्दर पैच करने के लिए आसान है, इसलिए कोड में ऐसा करना बेहतर है।
रीब

2
@jxramos: ओपी ने पायथन 2.7 का उपयोग किया, ट्रेसबैक से स्पष्ट। Ideone.com (Python 3.7.3) पर एक त्वरित परीक्षण से पता चलता है कि stdlib jsonलाइब्रेरी को अपडेट कर दिया गया है और नई त्रुटि प्रारूप प्रारूप देता है। हालांकि अभी मेरे पास सटीक रिलीज़ ट्रैक करने का समय नहीं है।
मार्टिन पीटर्स

1
@jxramos ने पाया, Python 3.5 ने अपवादों को अपडेट किया: Bugs.python.org/issue19361 ( docs.python.org/3/whatsnew/3.5.html#improved-modules के माध्यम से )।
मार्टिन पीटर्स

15

आप यह बताने में सक्षम नहीं होंगे कि JSON कहां गलत है। आपको इस तरह से कहीं ऑनलाइन एक लिंटर का उपयोग करने की आवश्यकता होगी

यह आपको उस JSON में त्रुटि दिखाएगा जिसे आप डिकोड करने का प्रयास कर रहे हैं।


2
क्या ऑफ़लाइन उपकरण हैं जो गोपनीय JSON फ़ाइलों के लिए ऐसा कर सकते हैं?
OJW

@OJW नहीं है कि मुझे पता है, लेकिन उस समस्या को हल करना चाहिए जो आप कर रहे हैं या कम से कम आपको अपने टूटे हुए जुओं को ठीक करने दें।
myusuf3

12
मेरी JSON फाइल ठीक है - मैं अपने प्रोग्राम को उपयोगी त्रुटि संदेश बनाने की कोशिश कर रहा हूं जो किसी के लिए भी समझ में आता है। उन्हें यह बताना "लाइन 13 कॉलम 32 पर उस अल्पविराम से छुटकारा पाएं" अच्छा है। उन्हें बताना "आपकी फ़ाइल में कहीं त्रुटि है, कृपया इसे इंटरनेट पर अपलोड करें जहां लोग आपकी सहायता करेंगे" खराब है।
OJW

7

आप यहां पाई जाने वाली आगजनी लाइब्रेरी की कोशिश कर सकते हैं: http://code.google.com/p/rson/ । मैं इसे PYPI: https://pypi.python.org/pypi/rson/0.9 पर भी जारी करता हूं ताकि आप इसे प्राप्त करने के लिए easy_install या पाइप का उपयोग कर सकें।

टॉम द्वारा दिए गए उदाहरण के लिए:

>>> rson.loads('[1,2,]')
...
rson.base.tokenizer.RSONDecodeError: Unexpected trailing comma: line 1, column 6, text ']'

RSON JSON का सुपरसेट होने के लिए डिज़ाइन किया गया है, इसलिए यह JSON फ़ाइलों को पार्स कर सकता है। इसमें एक वैकल्पिक वाक्यविन्यास भी है जो मनुष्यों को देखने और संपादित करने के लिए बहुत अच्छा है। मैं इसे इनपुट फ़ाइलों के लिए काफी उपयोग करता हूं।

बूलियन मूल्यों के पूंजीकरण के लिए: ऐसा प्रतीत होता है कि आग में गलत तरीके से पूंजीकृत बूलियन को तार के रूप में पढ़ा जाता है।

>>> rson.loads('[true,False]')
[True, u'False']

4

मुझे इसी तरह की समस्या थी और यह एकल्यूकोट्स के कारण था। JSON मानक ( http://json.org ) केवल दोहरे उद्धरण चिह्नों का उपयोग करने के बारे में बात करता है, इसलिए यह होना चाहिए कि अजगर jsonपुस्तकालय केवल दोहरे उद्धरण चिह्नों का समर्थन करता है।


3

इस समस्या के अपने विशेष संस्करण के लिए, मैं आगे बढ़ा और फ़ाइल के load_json_file(path)भीतर फ़ंक्शन की घोषणा की खोज की packaging.py, फिर printउसमें एक लाइन की तस्करी की :

def load_json_file(path):
    data = open(path, 'r').read()
    print data
    try:
        return Bunch(json.loads(data))
    except ValueError, e:
        raise MalformedJsonFileError('%s when reading "%s"' % (str(e),
                                                               path))

इस तरह यह ट्रायल-कैच में प्रवेश करने से पहले json फाइल की सामग्री को प्रिंट करेगा, और इस तरह से - यहां तक ​​कि मेरे बमुश्किल मौजूदा पायथन ज्ञान के साथ - मैं जल्दी से यह पता लगाने में सक्षम था कि मेरा कॉन्फ़िगरेशन json फाइल क्यों नहीं पढ़ सकता है।
(ऐसा इसलिए था क्योंकि मैंने UTF-8 BOM ... बेवकूफ लिखने के लिए अपना टेक्स्ट एडिटर सेट किया था)

सिर्फ इस बात का उल्लेख करते हुए, क्योंकि शायद ओपी की विशिष्ट समस्या का एक अच्छा जवाब नहीं है, यह एक बहुत ही उत्पीड़क बग के स्रोत का निर्धारण करने में एक त्वरित तरीका था। और मैं शर्त लगाता हूं कि बहुत से लोग इस लेख पर ठोकर खाएंगे जो एक के लिए एक अधिक क्रिया समाधान खोज रहे हैं MalformedJsonFileError: No JSON object could be decoded when reading …। ताकि उनकी मदद हो सके।


आपको फ़ाइल I / O ( with open(fn) as f) के लिए संदर्भ प्रबंधक का उपयोग करना चाहिए , यह आपके लिए अपवाद में फ़ाइल को बंद करने का काम करता है। en.wikibooks.org/wiki/Python_Programming/…
रीब

1
+1। यदि आप मानक व्यवहार पर उस बंदर को पकड़ने का एक उदाहरण दिखा सकते हैं, तो वह बहुत साफ
क्रेग ब्रेट

क्षमा करें, मैंने कभी भी किसी पायथन कोड को नहीं छुआ, क्योंकि समस्या का पता चल गया था। शायद कोई और मदद कर सकता है?
वुड्रोशाइगरु

3

मेरे लिए, मेरी json फ़ाइल बहुत बड़ी है, जब jsonअजगर में आम का उपयोग किया जाता है, तो यह उपरोक्त त्रुटि है।

simplejsonद्वारा स्थापित करने के बाद sudo pip install simplejson

और फिर मैंने इसे हल किया।

import json
import simplejson


def test_parse_json():
    f_path = '/home/hello/_data.json'
    with open(f_path) as f:
        # j_data = json.load(f)      # ValueError: No JSON object could be decoded
        j_data = simplejson.load(f)  # right
    lst_img = j_data['images']['image']
    print lst_img[0]


if __name__ == '__main__':
    test_parse_json()

1

मुझे एक समान समस्या थी यह मेरा कोड था:

    json_file=json.dumps(pyJson)
    file = open("list.json",'w')
    file.write(json_file)  

    json_file = open("list.json","r")
    json_decoded = json.load(json_file)
    print json_decoded

समस्या यह थी कि मैं भूल गया था मैंने file.close() इसे किया और समस्या को ठीक किया।


मेरे लिए भी काम किया, पता नहीं क्यों पहले यह समस्या नहीं थी।
1933 में pceccon

आपको फ़ाइल I / O ( with open(fn) as f) के लिए संदर्भ प्रबंधक का उपयोग करना चाहिए , यह आपके लिए अपवाद में फ़ाइल को बंद करने का काम करता है। en.wikibooks.org/wiki/Python_Programming/…
रीब

0

समस्या को ठीक करने के लिए स्वीकृत उत्तर सबसे आसान है। लेकिन अगर आपको अपनी कंपनी की नीति के कारण सिंपलसन स्थापित करने की अनुमति नहीं है, तो मैं "किसी सूची में अंतिम आइटम पर अल्पविराम का उपयोग करने" के विशेष मुद्दे को ठीक करने के लिए नीचे दिए गए प्रस्ताव का प्रस्ताव करता हूं :

  1. वर्ग "JSONDecoder" से inherite और ओवरराइड करने के लिए एक बच्चे के वर्ग "JSONLintCheck" बनाएँ init वर्ग "JSONDecoder" नीचे की तरह की विधि:

    def __init__(self, encoding=None, object_hook=None, parse_float=None,parse_int=None, parse_constant=None, strict=True,object_pairs_hook=None)        
            super(JSONLintCheck,self).__init__(encoding=None, object_hook=None,      parse_float=None,parse_int=None, parse_constant=None, strict=True,object_pairs_hook=None)
            self.scan_once = make_scanner(self)
  1. make_scanner एक नया फ़ंक्शन है जो उपरोक्त वर्ग के 'स्कैन_ऑनस' पद्धति को ओवरराइड करने के लिए उपयोग किया जाता है। और यहाँ इसके लिए कोड है it
  1 #!/usr/bin/env python
  2 from json import JSONDecoder
  3 from json import decoder
  4 import re
  5
  6 NUMBER_RE = re.compile(
  7     r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?',
  8     (re.VERBOSE | re.MULTILINE | re.DOTALL))
  9
 10 def py_make_scanner(context):
 11     parse_object = context.parse_object
 12     parse_array = context.parse_array
 13     parse_string = context.parse_string
 14     match_number = NUMBER_RE.match
 15     encoding = context.encoding
 16     strict = context.strict
 17     parse_float = context.parse_float
 18     parse_int = context.parse_int
 19     parse_constant = context.parse_constant
 20     object_hook = context.object_hook
 21     object_pairs_hook = context.object_pairs_hook
 22
 23     def _scan_once(string, idx):
 24         try:
 25             nextchar = string[idx]
 26         except IndexError:
 27             raise ValueError(decoder.errmsg("Could not get the next character",string,idx))
 28             #raise StopIteration
 29
 30         if nextchar == '"':
 31             return parse_string(string, idx + 1, encoding, strict)
 32         elif nextchar == '{':
 33             return parse_object((string, idx + 1), encoding, strict,
 34                 _scan_once, object_hook, object_pairs_hook)
 35         elif nextchar == '[':
 36             return parse_array((string, idx + 1), _scan_once)
 37         elif nextchar == 'n' and string[idx:idx + 4] == 'null':
 38             return None, idx + 4
 39         elif nextchar == 't' and string[idx:idx + 4] == 'true':
 40             return True, idx + 4
 41         elif nextchar == 'f' and string[idx:idx + 5] == 'false':
 42             return False, idx + 5
 43
 44         m = match_number(string, idx)
 45         if m is not None:
 46             integer, frac, exp = m.groups()
 47             if frac or exp:
 48                 res = parse_float(integer + (frac or '') + (exp or ''))
 49             else:
 50                 res = parse_int(integer)
 51             return res, m.end()
 52         elif nextchar == 'N' and string[idx:idx + 3] == 'NaN':
 53             return parse_constant('NaN'), idx + 3
 54         elif nextchar == 'I' and string[idx:idx + 8] == 'Infinity':
 55             return parse_constant('Infinity'), idx + 8
 56         elif nextchar == '-' and string[idx:idx + 9] == '-Infinity':
 57             return parse_constant('-Infinity'), idx + 9
 58         else:
 59             #raise StopIteration   # Here is where needs modification
 60             raise ValueError(decoder.errmsg("Expecting propert name enclosed in double quotes",string,idx))
 61     return _scan_once
 62
 63 make_scanner = py_make_scanner
  1. नए चाइल्ड क्लास के साथ मिलकर एक फाइल में 'make_scanner' फंक्शन को बेहतर तरीके से डालें।

0

बस उसी मुद्दे को मारा और मेरे मामले में समस्या BOMफ़ाइल की शुरुआत में (बाइट ऑर्डर मार्क) से संबंधित थी ।

json.tool खाली फ़ाइल (सिर्फ घुंघराले ब्रेसिज़) को संसाधित करने से इंकार कर दूंगा जब तक कि मैं UTF BOM मार्क को हटा नहीं देता।

मैंने क्या किया है:

  • vim के साथ मेरी json फ़ाइल खोली,
  • बाइट ऑर्डर मार्क हटा दिया गया ( set nobomb)
  • फाइल सुरक्षित करें

इससे json.tool के साथ समस्या का समाधान हो गया। उम्मीद है की यह मदद करेगा!


-1

जब आपकी फाइल बन जाएगी। इसके बजाय सामग्री के साथ एक फ़ाइल बनाने के लिए खाली है। से बदलो:

json.dump({}, file)

-3

आप cjson का उपयोग कर सकते हैं , जो शुद्ध-पायथन कार्यान्वयन की तुलना में 250 गुना अधिक तेज होने का दावा करता है, यह देखते हुए कि आपके पास "कुछ लंबी जटिल JSON फाइल है" और आपको संभवतः इसे कई बार चलाने की आवश्यकता होगी (डिकोडर विफल हो जाते हैं और पहली त्रुटि की रिपोर्ट करते हैं। केवल मुठभेड़)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.