There is a rule in Python programming called "it is Easier to Ask for Forgiveness than for Permission" (in short: EAFP). It means that you should catch exceptions instead of checking values for validity.

Thus, try the following:

try:
    qByUser = byUsrUrlObj.read()
    qUserData = json.loads(qByUser).decode('utf-8')
    questionSubjs = qUserData["all"]["questions"]
except ValueError:  # includes simplejson.decoder.JSONDecodeError
    print('Decoding JSON has failed')

EDIT: Since simplejson.decoder.JSONDecodeError actually inherits from ValueError (proof here), I simplified the catch statement by just using ValueError.

Answer from Tadeck on Stack Overflow
Top answer
1 of 2
240

There is a rule in Python programming called "it is Easier to Ask for Forgiveness than for Permission" (in short: EAFP). It means that you should catch exceptions instead of checking values for validity.

Thus, try the following:

try:
    qByUser = byUsrUrlObj.read()
    qUserData = json.loads(qByUser).decode('utf-8')
    questionSubjs = qUserData["all"]["questions"]
except ValueError:  # includes simplejson.decoder.JSONDecodeError
    print('Decoding JSON has failed')

EDIT: Since simplejson.decoder.JSONDecodeError actually inherits from ValueError (proof here), I simplified the catch statement by just using ValueError.

2 of 2
55

If you don't mind importing the json module, then the best way to handle it is through json.JSONDecodeError (or json.decoder.JSONDecodeError as they are the same) as using default errors like ValueError could catch also other exceptions not necessarily connected to the json decode one.

from json.decoder import JSONDecodeError


try:
    qByUser = byUsrUrlObj.read()
    qUserData = json.loads(qByUser).decode('utf-8')
    questionSubjs = qUserData["all"]["questions"]
except JSONDecodeError as e:
    # do whatever you want

//EDIT (Oct 2020):

As @Jacob Lee noted in the comment, there could be the basic common TypeError raised when the JSON object is not a str, bytes, or bytearray. Your question is about JSONDecodeError, but still it is worth mentioning here as a note; to handle also this situation, but differentiate between different issues, the following could be used:

from json.decoder import JSONDecodeError


try:
    qByUser = byUsrUrlObj.read()
    qUserData = json.loads(qByUser).decode('utf-8')
    questionSubjs = qUserData["all"]["questions"]
except JSONDecodeError as e:
    # do whatever you want
except TypeError as e:
    # do whatever you want in this case
🌐
Python
docs.python.org › 3 › library › json.html
JSON encoder and decoder — Python 3.14.3 documentation
1 month ago - >>> # Neither of these calls raises an exception, but the results are not valid JSON >>> json.dumps(float('-inf')) '-Infinity' >>> json.dumps(float('nan')) 'NaN' >>> # Same when deserializing >>> json.loads('-Infinity') -inf >>> json.loads('NaN') nan · In the serializer, the allow_nan parameter can be used to alter this behavior. In the deserializer, the parse_constant parameter can be used to alter this behavior. The RFC specifies that the names within a JSON object should be unique, but does not mandate how repeated names in JSON objects should be handled. By default, this module does not raise an exception; instead, it ignores all but the last name-value pair for a given name:
Discussions

JSONDecodeError exception's message - verbose - Ideas - Discussions on Python.org
Issue One of the porposes of exception’s message is to help the developer to identify the root cause of the bug and fix it. Currently, JSONDecodeError doesn’t do it well enough. Consider the following example: import json import requests try: server_raw_response = requests.get(url) ... More on discuss.python.org
🌐 discuss.python.org
1
July 17, 2024
How to get error location from json.loads in Python - Stack Overflow
I think it would be nicer if the json parser returned a more qualified Exception which contains these fields. I have opened an issue for it. More on stackoverflow.com
🌐 stackoverflow.com
Exception handling in Python - Am I doing this wrong (and why?) - Software Engineering Stack Exchange
I've read many questions and articles on exception handling in Python (and in general), but I still think that it's the most confusing thing ever. I ended up doing something like this: # error cla... More on softwareengineering.stackexchange.com
🌐 softwareengineering.stackexchange.com
September 27, 2015
Python handling exceptions while reading JSON files - Stack Overflow
My guess is, that whenever an exception occurs in a context manager (in the with statement), it closes the resource, which is why it isn't able to read r. ... The try statement j = json.load(r) implicitly reads the file moving the file's cursor to the end. More on stackoverflow.com
🌐 stackoverflow.com
🌐
Medium
medium.com › @saifulj1234 › handling-errors-exceptions-and-manipulating-json-data-in-python-2900353cca1f
Handling Errors, Exceptions and Manipulating JSON data in Python | by Saiful Rahman | Medium
July 23, 2022 - In this article, I gonna summarize some advanced topics in Python such as errors and exceptions. I learned how to avoid the errors which crash the application program by handling those errors. And we take a look at a particular data format called JSON stands for JavaScriptObjectNotation data format which is widely used to transfer data across the internet between applications.
🌐
Claudia Kuenzler
claudiokuenzler.com › blog › 1394 › how-to-handle-json-decode-error-python-script-try-except
How to handle JSON decode error in Python script with try and except
February 20, 2024 - Luckily my toot (a post on Mastodon) received a few comments and hints and it turns out that JSONDecodeError is indeed an error which can be used in the exception handling. However the error handler JSONDecodeError does not exist in the "global" namespace of the Python script and needs to be called from the json module: try: data = json.loads(output) except json.JSONDecodeError as e: print("Error: Unable to decode JSON, Error: {}. Manually run command ({}) to verify JSON output.".format(e, cmd))
🌐
Amandinemlee
amandinemlee.com › 2017 › 03 › 20 › Python-exception-handling
Python Exception Handling - Amandine Lee
My interpretation of Meyer’s work, in the context of Python, is that assertions can be used to make it really clear what is at fault when something goes wrong. In fact, that should be the primary goal of all exception handling: ease of debugging. ... import json FOO_FILE = 'somefile.json' def get_foo(filename: str) -> Optional[int]: """Return the integer value of `foo` in JSON-encoded dictionary, if found.
🌐
Python.org
discuss.python.org › ideas
JSONDecodeError exception's message - verbose - Ideas - Discussions on Python.org
July 17, 2024 - Issue One of the porposes of exception’s message is to help the developer to identify the root cause of the bug and fix it. Currently, JSONDecodeError doesn’t do it well enough. Consider the following example: import json import requests try: server_raw_response = requests.get(url) server_json_response = json.loads(server_raw_response) except JSONDecodeError as error: print(error) # JSONDecodeError: Expecting , delimiter: line 1 column 23 (char 22) Can you understand what is th...
🌐
Career Karma
careerkarma.com › blog › python › python jsondecodeerror explanation and solution
Python JSONDecodeError Explanation and Solution | CK
December 1, 2023 - Alternatively, we could use a try…except handler to handle this issue so that our code will not immediately return an error if we face another formatting issue: import json try: with open("equipment.json") as file: data = json.load(file) print("Equipment data has been successfully retrieved.") except json.decoder.JSONDecodeError: print("There was a problem accessing the equipment data.")
Top answer
1 of 4
10

[This answer is outdated. See other answers for modern python versions]

Scanning the json/decoder.py source code, we can see that the decoder's error messages are constructed using the errmsg function:

Copydef errmsg(msg, doc, pos, end=None):
    # Note that this function is called from _json
    lineno, colno = linecol(doc, pos)
    if end is None:
        fmt = '{0}: line {1} column {2} (char {3})'
        return fmt.format(msg, lineno, colno, pos)
        #fmt = '%s: line %d column %d (char %d)'
        #return fmt % (msg, lineno, colno, pos)
    endlineno, endcolno = linecol(doc, end)
    fmt = '{0}: line {1} column {2} - line {3} column {4} (char {5} - {6})'
    return fmt.format(msg, lineno, colno, endlineno, endcolno, pos, end)
    #fmt = '%s: line %d column %d - line %d column %d (char %d - %d)'
    #return fmt % (msg, lineno, colno, endlineno, endcolno, pos, end)

Since this is a pure-python module, it's easy to wrap this function with a custom one. This process is known as monkey patching:

Copyimport json

original_errmsg= json.decoder.errmsg

def our_errmsg(msg, doc, pos, end=None):
    json.last_error_position= json.decoder.linecol(doc, pos)
    return original_errmsg(msg, doc, pos, end)

json.decoder.errmsg= our_errmsg

try:
    data = json.loads('{1:}')
except ValueError as e:
    print("error at", json.last_error_position)

Obviously, this solution is not ideal, since the implementation may change at any time, although it's still better than relying on the message. You should check if errmsg exists before patching (and possibly if there's no other arguments, or use varargs).

2 of 4
5

If you use simplejson library, you get a well qualified JSONDecodeError:

Copyclass JSONDecodeError(ValueError):
   """Subclass of ValueError with the following additional properties:

   msg: The unformatted error message
   doc: The JSON document being parsed
   pos: The start index of doc where parsing failed
   end: The end index of doc where parsing failed (may be None)
   lineno: The line corresponding to pos
   colno: The column corresponding to pos
   endlineno: The line corresponding to end (may be None)
   endcolno: The column corresponding to end (may be None)

   """

Hopefully, this will be merged into stdlib soon.

Find elsewhere
🌐
ProgramCreek
programcreek.com › python › example › 279 › json.load
Python Examples of json.load
def get_models(model_files): """ return all the models from list of model files (.json) for processing """ model = [] for file in model_files: if file.endswith("_model.json"): with open(file, 'r') as input_stream: try: loadedData = json.load(input_stream) if(len(loadedData) > 0): model.append(loadedData) except ValueError: script_output("Invalid JSON in " + file) exit(1) else: script_output("File does not end with _model.json found") script_output(file, False) exit(1) return model
🌐
ProgramCreek
programcreek.com › python › example › 95917 › json.JSONDecodeError
Python Examples of json.JSONDecodeError
def _onMessage(self, msg): try: data = json.loads(msg) except json.JSONDecodeError: # Something wrong with this data, log and discard return if isinstance(data, dict): if 'topics' in data: self._response_handler(data['topics']) elif 'type' in data: type = data.pop('type') self._data_handler(type, data) else: pass ·
Top answer
1 of 2
10

User input sucks. You can't trust those users to get anything right, and so you've got to handle all kinds of special cases that make your life difficult. Having said that, we can minimize the difficulty with general principles.

Validate early, not often

Check input for validity as soon as it read into your program. If you read in a string that should be a number, convert it into a number right away and complain to the user if it isn't a number. Any rogue data you don't verify at input will make its way into the rest of the program and produce bugs.

Now, you can't always do this. There will be cases where you can't verify the correct properties right away, and you'll have to verify them during later processing. But you want as much verification to happen as early as possible so that you have your special cases around input logic centralized to one location as much as possible.

Use Schemas

Let's consider a function that parses some json.

def parse_student(text):
    try: 
        data = json.parse(text)
    except ValueError as error:
        raise ParseError(error)

    if not isinstance(data, dict):
        raise ParseError("Expected an object!")
    
    try:
        name = data['name']
    except KeyError:
        raise ParseError('Expected a name')

    if not isinstance(name, dict):
       raise ParseError("Expected an object for name")

    try:
        first = name['first']
    except KeyError:
        raise ParseError("Expected a first name")
    
    if not isinstance(first, basestring):
        raise ParseError("Expected first name to be a string")
    
    if first == '':
        raise ParseError("Expected non-empty first name")

That was a lot of work just to extract the first name, let alone any other attributes. We can make this a lot better if we can use a json-schema. See: http://json-schema.org/.

I can describe what my student object looks like:

{
    "type": "object",
    "properties": {
        "name": {
            "type": "object",
            "properties": {
                  "first" : {
                       "type" : "string"
                  }
            },
            "required": "first"
        },
    } 
    "required": ["name"]
}

When I parse I then do something like:

def parse_student(text):
    try: 
        data = json.parse(text)
    except ValueError as error:
        raise ParseError(error)

    try:
        validate(data, STUDENT_SCHEMA)
    except ValidationError as error:
        raise ParseError(error)

    first = data['name']['first']

Checking against the schema verifies most of the structure that I need. If the user input does not match the schema, the schema validator will produce a nice error message explaining exactly what was wrong. It will do so far more consistently and correctly then if I wrote the checking code by hand. Once the validation has been passed, I can just grab data out of the json object, because I know that it will have the correct structure.

Now, you probably aren't parsing JSON. But you may find that you can do something similar for your format that lets you reuse the basic validation logic across the different pieces of information that you fetch.

2 of 2
2

You can probably simplify your code by centralising the try/except validation of function args, and the conversion of exceptions to your exception class, into one or two decorators, which you apply to each of your methods and functions. google for python decorators for exceptions, and python decorators to validate args and you'll find stackoverflow examples like this and this.

You often don't need to explicitly validate method arguments as your code is going to cause exceptions naturally, and this might be good enough, as you cannot test for all eventualities.

Remember when writing a script, that often that your code will be even more useful if someone can include it as a library module, so make the main be specific to what a user would like from the command line, but in the library part don't try too hard to obscure where an exception stems from and so on.

🌐
GitHub
github.com › Adyen › adyen-python-api-library › issues › 43
Unhandled exceptions on json.loads give no clues on connection errors to Adyen · Issue #43 · Adyen/adyen-python-api-library
November 24, 2017 - To make the problem worse this exception tell us nothing about what we are sending and receiving to Adyen servers, and so we can't investigate the problem because we have no clues about it. We need that devs handle the json_lib.loads call at https://github.com/Adyen/adyen-python-api-library/blob/1.1.0/Adyen/client.py#L413 and instead ValueError return an AdyenInvalidRequestError with request information so we can investigate the problem.
Author   felipe-prenholato
🌐
GeeksforGeeks
geeksforgeeks.org › python › json-parsing-errors-in-python
JSON Parsing Errors in Python - GeeksforGeeks
July 23, 2025 - import json json_data = '{ "person": { "name": "Om Mishra", "age": 30 } }' try: data = json.loads(json_data) name = data["person"].name print(name) except AttributeError: print("Invalid key in JSON data. Expected 'name' key to be present.") ... Invalid key in JSON data. Expected 'name' key to be present. ... In this example, we try to access the name attribute of the person object in the data dictionary using dot notation. However, the name attribute does not exist in the person object, so Python raises an AttributeError with the message "'dict' object has no attribute 'name'".
Top answer
1 of 2
5

The purpose of capturing exceptions is to control the program's behavior when something bad happened, but in an expected way. If you are not even sure what would cause that exception happen, capturing it would only swallow the underlying programming errors you might have.

I wouldn't add as many kinds of exception as possible to that single block of code, you should only add what you care about. To take it to extreme, each line of code would yield certain exceptions but for obvious reason you couldn't do try except for all of them.

Edit:

For the sake of correctness, since you mentioned I don't want my code to break in any case, you could simply do:

try:
    # json.load
except Exception as e:
    print "Let's just ignore all exceptions, like this one: %s" % str(e)

This is would give you what exception happens as output.

2 of 2
1
import random
import sys


def main():
    """Demonstrate the handling of various kinds of exceptions."""
    # This is like what you are doing in your code.
    exceptions = IOError, RuntimeError, ValueError
    try:
        raise random.choice(exceptions)()
    except exceptions as error:
        print('Currently handling:', repr(error))
    # The following is not much different from Shang Wang's answer.
    try:
        raise random.choice(exceptions)()
    except Exception as error:
        print('Currently handling:', repr(error))
    # However, the following code will sometimes not handle the exception.
    exceptions += SystemExit, KeyboardInterrupt, GeneratorExit
    try:
        raise random.choice(exceptions)()
    except Exception as error:
        print('Currently handling:', repr(error))
    # The code can be slightly altered to take the new errors into account.
    try:
        raise random.choice(exceptions)()
    except BaseException as error:
        print('Currently handling:', repr(error))
    # This does not take into account classes not in the exception hierarchy.
    class Death:
        pass
    try:
        raise Death()
    except BaseException as error:
        print('Currently handling:', repr(error))
    # If your version of Python does not consider raising an exception from an
    # instance of a class not derived from the BaseException class, the way to
    # get around this problem would be with the following code instead.
    try:
        raise Death()
    except:
        error = sys.exc_info()[1]
        print('Currently handling:', repr(error))


if __name__ == '__main__':
    main()
🌐
Quora
quora.com › How-can-you-handle-errors-when-parsing-JSON-in-Python
How to handle errors when parsing JSON in Python - Quora
Answer: Handling Errors, Exceptions and Manipulating JSON data in Python 1. Errors and Exceptions. 2. try keyword comes with a block of code where we execute something that might cause an exception. ... 3. except block, the next step is to define the except block of code that you want the progra...
🌐
Reddit
reddit.com › r/learnpython › i get an error whenever i try to use "json.load"
r/learnpython on Reddit: I get an error whenever I try to use "json.load"
August 8, 2022 -

JSON doc:

{
    "Data" : [
        "input1",
        "input2",
        "input3",
        "input4"
    ]
}

Python code:

import json
with open("data.json", 'r') as f:
    json_data = json.load(f)
print(json_data)

Error message:

sh-5.1$ /bin/python /home/USER/Documents/Python/learning
Traceback (most recent call last):
  File "/home/USER/Documents/Python/learning", line 27, in <module>
    json_data = json.load(f)
  File "/usr/lib/python3.9/json/__init__.py", line 293, in load
    return loads(fp.read(),
  File "/usr/lib/python3.9/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.9/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.9/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Disproved theories: Improper syntax (python), document not located, bad formatting (json), accidental empty space in json.

I get this error each time I try to use "json.load" so long as it has a valid parameter input. Whether read or write; error. I'm using Visual Studio Code on Linux Mint in case that matters.

Thanks for your time! I'll be happy to answer questions in the morning when I wake up.

EDIT: Clarity, and reddit dislikes my use of backticks. Manually tabbed code.

EDIT: This code SHOULD work. It does on other computers. But it doesn't on mine, and I don't know why nor how to fix it.

🌐
Medium
lynn-kwong.medium.com › python-json-tricks-how-to-deal-with-jsondecodeerror-2353464814bc
Python JSON tricks: how to deal with JSONDecodeError | by Lynn G. Kwong | Medium
October 31, 2024 - A JSON looks like the dictionary type in Python, but they are different. The essential difference is that a JSON is a pure string that has a strict format. If you don’t write it properly, you may have unexpected errors.
🌐
Stack Overflow
stackoverflow.com › questions › 64182380 › handling-json-loads-value-error-in-python
Handling json.loads() Value Error in python - Stack Overflow
You can’t handle value errors during parsing of json. It is either entirely correct or there is an error. If you want to detect invalid values you have to do that yourself. Did you mean: ‘input = '{"a":null}’. ? ... I'm not sure what is the expected output that you seek (it will be great if you could also add it). The following code will perform without any errors: import json import re in1 = '{"Number": nan}' in1 = re.sub(r'\bnan\b', 'NaN', in1) print(json.loads(in1)) # {'Number': nan} in2 = '{"name":"siva","details":{"id":"111","qualification":nan},"marks":[{"grade1":90,"grade2":null,"grade3":NaN}]}' in2 = re.sub(r'\bnan\b', 'NaN', in2) print(json.loads(in2)) # {'name': 'siva', 'details': {'id': '111', 'qualification': nan}, 'marks': [{'grade1': 90, 'grade2': None, 'grade3': nan}]}