添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

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

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

(note: the best code version should be:

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

but both exhibit similar behavior)

For many types of JSON error (missing delimiters, incorrect backslashes in strings, etc), this prints a nice helpful message containing the line and column number where the JSON error was found.

However, for other types of JSON error (including the classic "using comma on the last item in a list", but also other things like capitalising true/false), Python's output is just:

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

For that type of ValueError, how do you get Python to tell you where is the error in the JSON file?

I'm not trying to find the error in a particular file now; I'm trying to modify my program so that it will highlight the error in any future file it reads. – OJW Feb 15, 2013 at 18:42

I've found that the simplejson module gives more descriptive errors in many cases where the built-in json module is vague. For instance, for the case of having a comma after the last item in a list:

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

which is not very descriptive. The same operation with simplejson:

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

Much better! Likewise for other common errors like capitalizing True.

Future versions of Python will include those improvements; it's the same project underneath. – Martijn Pieters Feb 19, 2013 at 13:04 @user2016290 Editing core/package files directly is a bad idea. Python is easy to monkey patch, so it's better to do that in code. – Rebs Nov 29, 2016 at 3:10 @jxramos: The OP used Python 2.7, as evident from the traceback. A quick test on ideone.com (Python 3.7.3) shows that the stdlib json library has been updated and gives the new error message format. I don’t have time to track exact releases right now however. – Martijn Pieters Mar 14, 2020 at 0:29 @jxramos found it, Python 3.5 updated the exceptions: bugs.python.org/issue19361 (via docs.python.org/3/whatsnew/3.5.html#improved-modules). – Martijn Pieters Mar 14, 2020 at 0:35

You wont be able to get python to tell you where the JSON is incorrect. You will need to use a linter online somewhere like this

This will show you error in the JSON you are trying to decode.

@OJW not that I know of but that should resolve the issue you are having or at least let you fix your broken json. – Mahdi Yusuf Feb 15, 2013 at 19:12 My JSON file is fine - I'm trying to make my program print useful error messages which are understandable to anybody. Telling them "get rid of that comma at line 13 column 32" is good. Telling them "there's an error somewhere in your file, please upload it to the internet where people will help you" is bad. – OJW Feb 15, 2013 at 21:15

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

For my particular version of this problem, I went ahead and searched the function declaration of load_json_file(path) within the packaging.py file, then smuggled a print line into it:

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

That way it would print the content of the json file before entering the try-catch, and that way – even with my barely existing Python knowledge – I was able to quickly figure out why my configuration couldn't read the json file.
(It was because I had set up my text editor to write a UTF-8 BOM … stupid)

Just mentioning this because, while maybe not a good answer to the OP's specific problem, this was a rather quick method in determining the source of a very oppressing bug. And I bet that many people will stumble upon this article who are searching a more verbose solution for a MalformedJsonFileError: No JSON object could be decoded when reading …. So that might help them.

You should use the context manager for file I/O (with open(fn) as f), it handles closing the file in an exception for you. en.wikibooks.org/wiki/Python_Programming/… – Rebs Nov 29, 2016 at 2:59 +1. If you could show an example of then monkeypatching that onto the standard behaviour, that'd be pretty neat – Craig Brett Apr 10, 2017 at 8:41 Sorry, I never touched any Python code after that problem was figured out. Maybe someone else can help? – WoodrowShigeru Apr 13, 2017 at 15:55

As to me, my json file is very large, when use common json in python it gets the above error.

After install simplejson by sudo pip install simplejson.

And then I solved it.

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()
                You should use the context manager for file I/O (with open(fn) as f), it handles closing the file in an exception for you. en.wikibooks.org/wiki/Python_Programming/…
– Rebs
                Nov 29, 2016 at 2:58
                Similarly, I was able to avoid the problem by opening the file with 'r' instead of 'w+' which I was unnecessarily doing
– Sterling Butters
                Jul 13 at 20:06

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

  • 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)
      6 NUMBER_RE = re.compile(
      7     r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?',
      8     (re.VERBOSE | re.MULTILINE | re.DOTALL))
     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
     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
     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
     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
     63 make_scanner = py_make_scanner
    
  • Better put the 'make_scanner' function together with the new child class into a same file.
  • 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!

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

    json.dump({}, file)
    
  •