Displaying better error message than “No JSON object could be decoded”

后端 未结 11 1011
既然无缘
既然无缘 2020-11-30 23:05

Python code to load data from some long complicated JSON file:

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

(note: the be

相关标签:
11条回答
  • 2020-12-01 00:02

    Just hit the same issue and in my case the problem was related to BOM (byte order mark) at the beginning of the file.

    json.tool would refuse to process even empty file (just curly braces) until i removed the UTF BOM mark.

    What I have done is:

    • opened my json file with vim,
    • removed byte order mark (set nobomb)
    • save file

    This resolved the problem with json.tool. Hope this helps!

    0 讨论(0)
  • 2020-12-01 00:03

    You could try the rson library found here: http://code.google.com/p/rson/ . I it also up on PYPI: https://pypi.python.org/pypi/rson/0.9 so you can use easy_install or pip to get it.

    for the example given by tom:

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

    RSON is a designed to be a superset of JSON, so it can parse JSON files. It also has an alternate syntax which is much nicer for humans to look at and edit. I use it quite a bit for input files.

    As for the capitalizing of boolean values: it appears that rson reads incorrectly capitalized booleans as strings.

    >>> rson.loads('[true,False]')
    [True, u'False']
    
    0 讨论(0)
  • 2020-12-01 00:03

    I had a similar problem and it was due to singlequotes. The JSON standard(http://json.org) talks only about using double quotes so it must be that the python json library supports only double quotes.

    0 讨论(0)
  • 2020-12-01 00:03

    The accepted answer is the easiest one to fix the problem. But in case you are not allowed to install the simplejson due to your company policy, I propose below solution to fix the particular issue of "using comma on the last item in a list":

    1. Create a child class "JSONLintCheck" to inherite from class "JSONDecoder" and override the init method of the class "JSONDecoder" like below:

      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 is a new function that used to override the 'scan_once' method of the above class. And here is code for 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. Better put the 'make_scanner' function together with the new child class into a same file.
    0 讨论(0)
  • 2020-12-01 00:03

    When your file is created. Instead of creating a file with content is empty. Replace with:

    json.dump({}, file)
    
    0 讨论(0)
提交回复
热议问题