แสดงข้อความผิดพลาดที่ดีกว่า“ ไม่มีวัตถุ 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 ประเภทอื่น ๆ (รวมถึงแบบคลาสสิก "การใช้เครื่องหมายจุลภาคในรายการสุดท้ายในรายการ" แต่ยังมีสิ่งอื่น ๆ เช่นการใช้อักษรตัวพิมพ์ใหญ่จริง / เท็จ) เอาต์พุตของ Python เป็นเพียง:

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 ประเภทนั้นคุณจะรับ Python อย่างไรเพื่อบอกคุณว่ามีข้อผิดพลาดในไฟล์ JSON อย่างไร


คุณสามารถคัดลอกข้อความที่ตัดตอนมาจากไฟล์ของคุณได้ไหม
Ketouem

ฉันไม่ได้พยายามหาข้อผิดพลาดในไฟล์ใดไฟล์หนึ่งตอนนี้ ฉันกำลังพยายามแก้ไขโปรแกรมของฉันเพื่อที่จะเน้นข้อผิดพลาดในไฟล์ที่จะอ่านในอนาคต
OJW

2
ไม่เกี่ยวข้องโดยตรง แต่คุณสามารถทำได้json.load(f)แทนjson.loads(f.read())
มาร์ตินแซมซั่น

@OJW หลามรุ่นนี้มีพฤติกรรมแบบไหน
jxramos

Python 3.8.1 ให้ตำแหน่งข้อผิดพลาด "ค่าที่คาดหวัง: บรรทัด 1 คอลัมน์ 21 (ถ่าน 20)"
OJW

คำตอบ:


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
Python เวอร์ชั่นอนาคตจะรวมการปรับปรุงเหล่านั้นไว้ด้วย มันเป็นโครงการเดียวกันภายใต้
Martijn Pieters


1
@ user2016290 การแก้ไขไฟล์ core / package โดยตรงเป็นความคิดที่ไม่ดี Python นั้นง่ายต่อการแก้ไขของ Monkey ดังนั้นมันจึงเป็นการดีที่จะทำในโค้ด
Rebs

2
@jxramos: OP ใช้ Python 2.7 ตามที่เห็นได้ชัดจากการย้อนกลับ การทดสอบอย่างรวดเร็วบน ideone.com (Python 3.7.3)แสดงว่าjsonไลบรารีstdlib ได้รับการปรับปรุงและให้รูปแบบข้อความแสดงข้อผิดพลาดใหม่ อย่างไรก็ตามฉันไม่มีเวลาที่จะติดตามการเปิดตัวที่แน่นอน
Martijn Pieters

1
@jxramos พบว่า Python 3.5 ได้อัปเดตข้อยกเว้น: bugs.python.org/issue19361 (ผ่านdocs.python.org/3/whatsnew/3.5.html#improved-modules )
Martijn Pieters

15

คุณจะไม่สามารถรับหลามเพื่อบอกคุณว่า JSON ไม่ถูกต้อง คุณจะต้องใช้ linter ออนไลน์ที่ไหนสักแห่งเช่นนี้

สิ่งนี้จะแสดงให้คุณเห็นข้อผิดพลาดใน JSON ที่คุณกำลังพยายามถอดรหัส


2
มีเครื่องมือออฟไลน์ที่สามารถทำได้สำหรับไฟล์ JSON ที่เป็นความลับหรือไม่?
OJW

@OJW ไม่ใช่สิ่งที่ฉันรู้ แต่ควรแก้ไขปัญหาที่คุณมีหรืออย่างน้อยก็ให้คุณแก้ไข json ที่ใช้งานไม่ได้
myusuf3

12
ไฟล์ JSON ของฉันใช้ได้ - ฉันพยายามทำให้โปรแกรมพิมพ์ข้อความแสดงข้อผิดพลาดที่เป็นประโยชน์ซึ่งใคร ๆ ก็เข้าใจได้ บอกให้พวกเขา "กำจัดเครื่องหมายจุลภาคที่บรรทัด 13 คอลัมน์ 32" เป็นสิ่งที่ดี บอกพวกเขาว่า "มีข้อผิดพลาดในไฟล์ของคุณโปรดอัปโหลดไปยังอินเทอร์เน็ตที่ผู้คนจะช่วยคุณ" ไม่ดี
OJW

7

คุณอาจจะลองห้องสมุด rson ที่นี่: http://code.google.com/p/rson/ ฉันยังใช้ PYPI: https://pypi.python.org/pypi/rson/0.9เพื่อให้คุณสามารถใช้ easy_install หรือ pip เพื่อรับได้

สำหรับตัวอย่างที่ได้รับจากทอม:

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

RSON ได้รับการออกแบบให้เป็นชุดของ JSON ดังนั้นจึงสามารถแยกวิเคราะห์ไฟล์ JSON ได้ นอกจากนี้ยังมีไวยากรณ์ทางเลือกซึ่งดีกว่ามากสำหรับมนุษย์ที่จะดูและแก้ไข ฉันใช้มันค่อนข้างน้อยสำหรับไฟล์อินพุต

สำหรับการใช้ประโยชน์จากค่าบูลีน: ปรากฏว่า rson อ่านบูลีนที่พิมพ์ใหญ่อย่างไม่ถูกต้องเป็นสตริง

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

4

ฉันมีปัญหาที่คล้ายกันและมันเกิดจาก singlequotes มาตรฐาน 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 ก่อนที่จะเข้าสู่ try-catch และด้วยวิธีนี้ - ถึงแม้จะมีความรู้เกี่ยวกับ Python ที่แทบจะไม่มีเลย - ฉันสามารถรู้ได้อย่างรวดเร็วว่าเหตุใดการกำหนดค่าของฉันจึงไม่สามารถอ่านไฟล์ json
(เป็นเพราะฉันได้ตั้งค่าโปรแกรมแก้ไขข้อความเพื่อเขียน UTF-8 BOM …โง่)

เพียงแค่พูดถึงเรื่องนี้เพราะในขณะที่อาจไม่ใช่คำตอบที่ดีสำหรับปัญหาเฉพาะของ OP แต่นี่เป็นวิธีที่รวดเร็วในการกำหนดแหล่งที่มาของบั๊กที่กดขี่ และฉันเดิมพันที่หลาย ๆ MalformedJsonFileError: No JSON object could be decoded when reading …คนจะสะดุดเมื่อบทความนี้ที่กำลังค้นหาวิธีการแก้ปัญหามากขึ้นอย่างละเอียดสำหรับ นั่นอาจช่วยพวกเขาได้


คุณควรใช้ context manager สำหรับไฟล์ I / O ( with open(fn) as f) มันจัดการการปิดไฟล์ในข้อยกเว้นสำหรับคุณ en.wikibooks.org/wiki/Python_Programming/…
Rebs

1
+1 หากคุณสามารถแสดงตัวอย่างของการจับลิงแล้วเข้าสู่พฤติกรรมมาตรฐานนั่นน่าจะเรียบร้อยดี
Craig Brett

ขออภัยฉันไม่เคยสัมผัสรหัส Python ใด ๆ หลังจากพบปัญหาแล้ว บางทีคนอื่นสามารถช่วยได้?
WoodrowShigeru

3

สำหรับฉันแล้วไฟล์ json ของฉันมีขนาดใหญ่มากเมื่อใช้งานทั่วไปjsonใน python จะได้รับข้อผิดพลาดด้านบน

หลังจากที่ติดตั้งโดยsimplejsonsudo 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() ฉันไปแล้วและแก้ไขปัญหา


ทำงานให้ฉันด้วยเหมือนกันไม่รู้ด้วยซ้ำว่าทำไมไม่มีปัญหานี้มาก่อน
pceccon

คุณควรใช้ context manager สำหรับไฟล์ I / O ( with open(fn) as f) มันจัดการการปิดไฟล์ในข้อยกเว้นสำหรับคุณ en.wikibooks.org/wiki/Python_Programming/…
Rebs

0

คำตอบที่ยอมรับนั้นเป็นคำตอบที่ง่ายที่สุดในการแก้ไขปัญหา แต่ในกรณีที่คุณไม่ได้รับอนุญาตให้ติดตั้ง simplejson เนื่องจากนโยบาย บริษัท ของคุณฉันเสนอวิธีแก้ปัญหาด้านล่างเพื่อแก้ไขปัญหาเฉพาะของ"การใช้เครื่องหมายจุลภาคในรายการสุดท้ายในรายการ" :

  1. สร้างคลาสย่อย "JSONLintCheck" เพื่อสืบทอดจากคลาส "JSONDecoder" และแทนที่เมธอด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เป็นฟังก์ชั่นใหม่ที่ใช้ในการแทนที่วิธีการ 'scan_once' ของชั้นเรียนดังกล่าวข้างต้น และนี่คือรหัสสำหรับมัน:
  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

สิ่งที่ฉันทำคือ:

  • เปิดไฟล์ json ของฉันด้วย vim
  • เครื่องหมายคำสั่งเอาออกไบต์ ( set nobomb)
  • บันทึกไฟล์

วิธีนี้แก้ไขปัญหาด้วย json.tool หวังว่านี่จะช่วยได้!


-1

เมื่อไฟล์ของคุณถูกสร้างขึ้น แทนที่จะสร้างไฟล์ที่มีเนื้อหาว่างเปล่า แทนที่ด้วย:

json.dump({}, file)

-3

คุณสามารถใช้cjsonซึ่งอ้างว่าเร็วกว่าการใช้งาน pure-python ถึง 250 เท่าเนื่องจากคุณมี "ไฟล์ JSON ที่ซับซ้อนนาน" และคุณอาจต้องเรียกใช้หลายครั้ง (ตัวถอดรหัสล้มเหลวและรายงานข้อผิดพลาดแรกที่พวกเขาใช้ พบเท่านั้น)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.