"JSON 객체를 디코딩 할 수 없음"보다 더 나은 오류 메시지 표시


128

길고 복잡한 JSON 파일에서 데이터를로드하는 Python 코드 :

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

(참고 : 최상의 코드 버전은 다음과 같아야합니다.

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

그러나 둘 다 비슷한 행동을 보입니다)

많은 유형의 JSON 오류 (구분 기호 누락, 문자열의 잘못된 백 슬래시 등)의 경우 JSON 오류가 발견 된 행 및 열 번호가 포함 된 유용한 메시지를 인쇄합니다.

그러나 다른 유형의 JSON 오류 (목록의 마지막 항목에 쉼표 사용)뿐만 아니라 true / false 대문자와 같은 다른 유형의 경우 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의 경우 JSON 파일에서 오류가 어디에 있는지 파이썬에게 알려주는 방법은 무엇입니까?


파일의 일부를 발췌 할 수 있습니까?
Ketouem

특정 파일에서 오류를 찾으려고하지 않습니다. 나중에 읽을 파일의 오류를 강조하도록 프로그램을 수정하려고합니다.
OJW

2
직접적으로 관련이 없지만 json.load(f)대신 할 수 있습니다json.loads(f.read())
Martin Samson

@OJW이 버전의 파이썬 버전은 무엇입니까?
jxramos

Python 3.8.1은 이제 "예상 값 : 1 행 21 열 (char 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 코어 / 패키지 파일을 직접 편집하는 것은 좋지 않습니다. 파이썬은 쉽게 패치 할 수 있으므로 코드에서하는 것이 좋습니다.
Rebs

2
@jxramos : OP는 역 추적에서 알 수 있듯이 Python 2.7을 사용했습니다. ideone.com (Python 3.7.3)에서 빠른 테스트를 수행 하면 stdlib json라이브러리가 업데이트되었으며 새 오류 메시지 형식이 표시됩니다. 그러나 지금 정확한 릴리스를 추적 할 시간이 없습니다.
Martijn Pieters

1
@jxramos는 파이썬 3.5가 예외를 업데이트했습니다 : bugs.python.org/issue19361 ( docs.python.org/3/whatsnew/3.5.html#improved-modules 통해 ).
Martijn Pieters

15

JSON이 잘못된 위치를 알려주는 파이썬을 얻을 수 없습니다. 같은 곳에서 온라인으로 린터를 사용해야합니다

디코딩하려는 JSON의 오류가 표시됩니다.


2
기밀 JSON 파일에 대해이를 수행 할 수있는 오프라인 도구가 있습니까?
OJW

@OJW는 내가 아는 것이 아니라 문제를 해결해야하거나 적어도 깨진 json을 수정하도록해야합니다.
myusuf3 2013

12
내 JSON 파일은 괜찮습니다. 프로그램을 다른 사람이 이해할 수있는 유용한 오류 메시지로 인쇄하려고합니다. "13 행 32 열에서 쉼표를 제거하십시오"라고 말하는 것이 좋습니다. "파일에 오류가있어 사람들이 도와 줄 인터넷에 업로드하십시오"라고 말하는 것은 좋지 않습니다.
OJW 2019

7

http://code.google.com/p/rson/ 에서 rson 라이브러리를 사용해 볼 수 있습니다 . 나는 또한 PYPI : https://pypi.python.org/pypi/rson/0.9 에 올라 서서 easy_install 또는 pip를 사용하여 얻을 수 있습니다.

tom이 제공 한 예 :

>>> 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

비슷한 문제가 있었고 작은 따옴표로 인해 발생했습니다. 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))

그렇게하면 try-catch에 들어가기 전에 json 파일의 내용을 인쇄 할 수 있습니다. 거의 기존 Python 지식조차도 내 구성이 json 파일을 읽을 수없는 이유를 신속하게 알 수있었습니다.
(UTF-8 BOM을 작성하도록 텍스트 편집기를 설정했기 때문에…

OP의 특정 문제에 대한 좋은 대답이 아닐 수도 있지만 이것은 매우 압도적 인 버그의 원인을 결정하는 다소 빠른 방법 이었기 때문에 이것을 언급하는 것입니다. 그리고 많은 사람들이이 기사에서 더 자세한 해결책을 찾고있는이 기사를 발견하게 될 것 MalformedJsonFileError: No JSON object could be decoded when reading …입니다. 도움이 될 수 있습니다.


파일 I / O ( with open(fn) as f)에 컨텍스트 관리자를 사용해야하며 , 예외로 파일 닫기를 처리합니다. en.wikibooks.org/wiki/Python_Programming/…
Rebs

1
+1. 표준 동작으로 몽키 패칭하는 예를 보여줄 수 있다면 꽤 깔끔합니다
Craig Brett

죄송합니다, 그 문제를 알아 낸 후에는 파이썬 코드를 건드리지 않았습니다. 다른 사람이 도울 수 있을까요?
WoodrowShigeru

3

나에 관해서는, 내 json 파일은 매우 커서 json파이썬에서 공통 으로 사용할 때 위의 오류가 발생합니다.

후 설치 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 2016 년

파일 I / O ( with open(fn) as f)에 컨텍스트 관리자를 사용해야하며 , 예외로 파일 닫기를 처리합니다. en.wikibooks.org/wiki/Python_Programming/…
Rebs

0

허용되는 답변은 문제를 해결하는 가장 쉬운 방법입니다. 그러나 회사 정책으로 인해 simplejson을 설치할 수없는 경우 아래 목록의 "목록의 마지막 항목에 쉼표를 사용 하는 " 문제를 해결하는 방법을 제안합니다 .

  1. "JSONDecoder"클래스에서 상속 할 "JSONLintCheck"하위 클래스를 작성하고 다음과 같이 "JSONDecoder"클래스 의 init 메소드를 대체하십시오 .

    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 마크를 제거 할 때까지 빈 파일 (중괄호 만) 처리를 거부합니다.

내가 한 일은 :

  • vim으로 내 json 파일을 열었습니다.
  • 삭제 된 바이트 순서 표시 ( set nobomb)
  • 파일을 저장

이것은 json.tool의 문제점을 해결했습니다. 도움이 되었기를 바랍니다!


-1

파일이 생성 될 때 내용이있는 파일을 만드는 대신 비어 있습니다. 다음으로 교체하십시오.

json.dump({}, file)

-3

"일부 복잡한 JSON 파일"이 있고 여러 번 실행해야 할 경우 (디코더가 실패하고 첫 번째 오류를보고 함) 순수 python 구현보다 최대 250 배 더 빠른 cjson을 사용할 수 있습니다. 만 발생).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.