Python
JSON
Parsing
Error
Debugging

Why can't Python parse this JSON data?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

When Python fails to parse JSON, the root cause is usually not the json module itself but invalid input or unexpected encoding. JSON is stricter than many developers expect, especially if the payload came from logs, manual edits, or another programming language. The fastest fix is to identify the exact violation and normalize the input before parsing.

JSON Is Not a Python Dictionary Literal

A common source of confusion is mixing Python syntax and JSON syntax. JSON requires double-quoted strings and property names, and it does not allow trailing commas.

This is valid Python data but invalid JSON:

python
bad_payload = "{'name': 'Ada', 'active': True,}"

This is valid JSON:

python
1import json
2
3good_payload = '{"name": "Ada", "active": true}'
4obj = json.loads(good_payload)
5print(obj["name"])  # Ada

Notice three differences:

  • Single quotes became double quotes.
  • True became lowercase true.
  • The trailing comma was removed.

If your input looks like a Python object dump, convert it at the source instead of trying to patch every malformed payload downstream.

Read the JSONDecodeError Precisely

json.loads usually tells you line and column where parsing stopped. Treat that location as a clue, not always the complete error boundary. Sometimes the real issue starts earlier and only becomes visible at the reported position.

python
1import json
2
3payload = '{"name": "Ada", "roles": ["admin", "dev",], "id": 7}'
4
5try:
6    json.loads(payload)
7except json.JSONDecodeError as exc:
8    print(f"Message: {exc.msg}")
9    print(f"Line: {exc.lineno}, Column: {exc.colno}, Position: {exc.pos}")

A useful debugging pattern is to print a short slice around exc.pos:

python
start = max(exc.pos - 20, 0)
end = min(exc.pos + 20, len(payload))
print(payload[start:end])

That local context helps spot bad commas, quotes, or missing delimiters quickly.

Handle Encoding and Transport Problems

Some parsing errors are not syntax mistakes in visible characters. They come from hidden bytes, encoding mismatches, or a byte order mark at the start of the string.

python
1import json
2
3raw_bytes = b'\xef\xbb\xbf{"event":"login","ok":true}'
4text = raw_bytes.decode("utf-8-sig")  # removes UTF-8 BOM if present
5obj = json.loads(text)
6print(obj)

If the payload comes from files or APIs:

  • Decode bytes explicitly before parsing.
  • Use utf-8 or utf-8-sig when BOM might appear.
  • Confirm you are parsing body content, not an HTML error page.

A surprisingly common production bug is calling json.loads on a server response that is actually a non-JSON message, such as authentication failure HTML.

Validate Input Before Parsing in Critical Paths

If malformed payloads are expected, validation and defensive checks keep your service stable.

python
1import json
2from pathlib import Path
3
4def load_json_file(path: str):
5    text = Path(path).read_text(encoding="utf-8")
6    if not text.strip():
7        raise ValueError("JSON input is empty")
8
9    try:
10        return json.loads(text)
11    except json.JSONDecodeError as exc:
12        snippet_start = max(exc.pos - 30, 0)
13        snippet_end = min(exc.pos + 30, len(text))
14        snippet = text[snippet_start:snippet_end]
15        raise ValueError(
16            f"Invalid JSON at line {exc.lineno}, col {exc.colno}. "
17            f"Nearby text: {snippet!r}"
18        ) from exc
19
20config = load_json_file("config.json")
21print(config)

This pattern gives your logs enough context to troubleshoot without exposing entire payloads.

Parsing and Serialization Are Different Failure Modes

Developers often say parsing failed when the code actually failed during serialization. For example, json.dumps fails on unsupported types unless you convert them first.

python
1import json
2from datetime import datetime
3
4record = {
5    "created_at": datetime.utcnow()
6}
7
8try:
9    json.dumps(record)
10except TypeError as exc:
11    print(exc)  # Object of type datetime is not JSON serializable
12
13serializable = {
14    "created_at": datetime.utcnow().isoformat()
15}
16print(json.dumps(serializable))

If you see TypeError about non-serializable objects, the issue is outbound encoding, not inbound parsing.

Common Pitfalls

  • Treating Python literals as JSON. Fix: Ensure all strings and keys use double quotes, booleans are lowercase, and commas are valid.
  • Ignoring JSONDecodeError location details. Fix: Use line, column, and nearby snippet output to pinpoint the actual fault.
  • Parsing bytes with unknown encoding. Fix: Decode explicitly using a known encoding, often utf-8 or utf-8-sig.
  • Assuming all HTTP responses are JSON. Fix: Check status code and Content-Type before parsing response body.
  • Confusing json.loads errors with json.dumps errors. Fix: Distinguish parse-time and serialize-time exceptions in logs.

Summary

  • Python usually fails to parse JSON because the input violates strict JSON syntax rules.
  • JSONDecodeError gives actionable coordinates that speed up debugging.
  • Hidden encoding issues, including BOM and wrong decoding, can break valid-looking payloads.
  • Validate and wrap parsing in clear error handling for production reliability.
  • Differentiate parsing failures from serialization failures to fix the right stage quickly.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.