Handling JSON Parsing Errors and Exceptions
json.loads() transforms a JSON string into a Python data structure by parsing the text and building corresponding lists, dictionaries, and primitive values.
Try it: Parsing JSON into Python
How json.loads() reads JSON text token by token and builds Python dicts, lists, strings, numbers, True/False and None, how an access path like data["users"][0]["name"] walks that structure, and what json.dumps() writes back.
How it works
- The scanner reads the next token: a brace or bracket, a string in double quotes, a number, true / false / null, or a ',' / ':' delimiter.
- '{' starts a Python dict and '[' a list; both are pushed on a parse stack until their closing '}' or ']'.
- Inside a dict every key must be a double-quoted string followed by ':' and a value; items are separated by ','.
- Anything else stops the parse with JSONDecodeError, reporting the message, line, column and character position.
- The access path is applied one subscript at a time: dicts take keys (KeyError if missing), lists take integer indexes (IndexError if out of range).
- json.dumps() turns the Python objects back into JSON text (True → true, None → null), optionally indented.
Default run (43 steps): json.loads() receives 105 characters of text. The scanner starts at char 0 and reads one token at a time. … json.dumps(data, indent=2) turns the Python objects back into JSON text (171 characters): True → true, None → null, and strings get double quotes.
Simplified: Written from scratch to match CPython 3.12's json module (messages and positions checked against it); input is limited to 400 characters and 24 nesting levels, and the access path accepts only ["key"] and [index] subscripts. Python 3.13 reports a trailing comma in an object with a different message.
Loading the simulation…
From Text to Structure
JSON often arrives as text. The function json.loads() reads that JSON string and builds a corresponding Python data structure. The result might contain lists, dictionaries, and primitive values. The original string does not change, so you should assign the returned Python object to a variable before working with it.
Tracing Nested User Data
Reading the First User's Name
A JSON string represents a list of users. Each user has the fields id, x, and name. How do you reach the first user's name after parsing?
- 1Parse the string
Pass the JSON string to
json.loads(). The outer square brackets describe a list, so the result is a Python list. - 2Select the first item
Use index 0 to select the first dictionary in the list.
- 3Select the name field
Use the key name on that dictionary to reach the user's name value.
The nested access pattern is info[0]['name']. For the generated example below, this produces Chuck.
import json
data = '[{"id": 1, "x": 10, "name": "Chuck"}, {"id": 2, "x": 20, "name": "Ada"}]'
info = json.loads(data)
print(type(info).__name__)
print(len(info))
print(info[0])
print(info[0]['name'])- 1The outer square brackets in the JSON text represent the list held by info.
- 2The first curly-braced item becomes the dictionary selected by info[0].
- 3The name key identifies the value Chuck inside that dictionary.
- The JSON string is stored in data.
json.loads(data)returns a Python list and assigns it to info.len(info)reports two list elements.- info[0] selects the first user dictionary.
- info[0]['name'] selects the name value from that dictionary.
list
2
{'id': 1, 'x': 10, 'name': 'Chuck'}
ChuckJSON and Python Representations
A JSON string and the Python object produced from it are different representations. Before parsing, the data is text. After json.loads() returns, Python has built a new object that can be navigated with Python syntax. The text remains unchanged, while the returned object is the value you inspect and access.
| JSON form | Python structure after parsing |
|---|---|
| Object described by curly braces | Dictionary |
| Array described by square brackets | List |
| JSON string value | Python string value |
| JSON number value | Python numeric value |
| JSON boolean or null value | Python primitive value |
The source explains that json.loads() builds corresponding lists, dictionaries, and primitive values. The table connects the JSON forms named in the topic to the Python structures created after parsing.
Diagnosing Parse and Access Failures
When parsing fails or the result is not what you expected, trace the operation in stages. First verify that the input is actually a string and contains valid JSON. Next confirm that you understand the structure of the parsed result. Finally check that your field names and indices match that structure. This separates a problem with parsing from a problem with accessing the parsed value.
Common mistake Forgetting to import json
What it looks likeCalling json.loads(data) without first importing the json module.
Why it failsThe name json has not been made available to the program.
Do this insteadImport the json module before calling json.loads().
Common mistake Passing a non-string object to json.loads()
What it looks likePassing an object that is already a Python data structure instead of JSON text.
Why it failsjson.loads()is used to parse a JSON string.Do this insteadVerify that the input is a string containing JSON before parsing.
Common mistake Using a field name that does not exist
What it looks likeTrying to access a key that is not present in the parsed dictionary.
Why it failsThe access expression does not match the structure represented by the JSON data.
Do this insteadInspect the parsed structure and confirm the exact field names.
Common mistake Using the wrong navigation order
What it looks likeTreating a list as if it were a dictionary or treating a dictionary as if it were a list.
Why it failsThe access syntax must match the structure created by parsing.
Do this insteadDetermine whether each layer is a list or dictionary, then use an index or key accordingly.
Why Documentation Matters
JSON is more concise than XML, but it is also less self-describing. The text contains fewer clues about what each value represents. To navigate a parsed response correctly, you need to know whether the outer structure is a list or dictionary, what each nested item contains, and which keys are available. API documentation provides this expected structure.
Suppose parsing produces a list whose first element is a dictionary with the key name. Write the access expression that reaches the name value of the first element.
Hints
- Use index 0 for the first list element.
- Use the key name for the dictionary field.
- Combine the two access operations.
What do you think happens?
After parsing a JSON string whose outer value is a list of two user dictionaries, what does len(info) report?
Reveal answer
2
The outer square brackets represent a list containing two user dictionaries, so the list has two elements.
A Reliable Parsing Routine
- 1Confirm that the json module is imported.
- 2Confirm that the value passed to
json.loads()is a string containing JSON. - 3Assign the return value of
json.loads()to a variable. - 4Determine whether the parsed result is organized as a list, dictionary, or another Python value.
- 5Use list indices and dictionary keys that match the documented structure.
- 6If an error occurs, inspect each layer step by step to find where your expectation differs from the actual structure.
Key Takeaways
json.loads()parses a JSON string and returns a new Python data structure; the original string remains unchanged.- The outer JSON shape determines whether the result begins as a Python list, dictionary, or another value.
- Nested access requires the correct combination of list indices and dictionary keys.
- JSON is concise but less self-describing, so documentation is important when navigating a response.
- Debug parsing problems in stages: verify the input, inspect the parsed structure, and then check each access key or index.