# How to Fix Python json.JSONDecodeError

The json.JSONDecodeError occurs when Python's json module fails to parse a string as valid JSON. This error provides detailed information about where and why the parsing failed, making it easier to diagnose malformed JSON data.

Error Patterns

Expecting Value

text
Traceback (most recent call last):
  File "app.py", line 5, in <module>
    json.loads('{"key": }')
json.JSONDecodeError: Expecting value: line 1 column 9 (char 8)

Expecting Property Name

text
Traceback (most recent call last):
  File "app.py", line 10, in <module>
    json.loads('{1: "value"}')
json.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

Extra Data

text
Traceback (most recent call last):
  File "app.py", line 15, in <module>
    json.loads('{"key": "value"}{"key2": "value2"}')
json.JSONDecodeError: Extra data: line 1 column 18 (char 17)

Invalid Control Character

text
Traceback (most recent call last):
  File "app.py", line 20, in <module>
    json.loads('"text\nwith\nnewlines"')
json.JSONDecodeError: Invalid control character at: line 1 column 6 (char 5)

Unterminated String

text
Traceback (most recent call last):
  File "app.py", line 25, in <module>
    json.loads('"unterminated string')
json.JSONDecodeError: Unterminated string starting at: line 1 column 1 (char 0)

Common Causes

  1. 1.Trailing commas - JSON doesn't allow trailing commas like Python
  2. 2.Single quotes - JSON requires double quotes for strings
  3. 3.Missing values - Key without value in object
  4. 4.Unquoted keys - Object keys must be in double quotes
  5. 5.Extra data - Multiple JSON objects in single string
  6. 6.Control characters - Unescaped newlines, tabs in strings
  7. 7.Invalid encoding - Non-UTF-8 encoding
  8. 8.Missing closing brackets - Unterminated objects or arrays

Diagnosis Steps

Step 1: Check Error Position

```python import json

try: data = json.loads(json_string) except json.JSONDecodeError as e: print(f"Error: {e.msg}") print(f"Line: {e.lineno}") print(f"Column: {e.colno}") print(f"Position (char): {e.pos}")

# Show context around error start = max(0, e.pos - 20) end = min(len(json_string), e.pos + 20) print(f"Context: ...{json_string[start:end]}...") print(f" {' ' * (min(20, e.pos - start) + 3)}^ Error here") ```

Step 2: Validate JSON Structure

```python import json

def diagnose_json(json_string): """Diagnose common JSON issues.""" print(f"String length: {len(json_string)}") print(f"First 50 chars: {json_string[:50]}") print(f"Last 50 chars: {json_string[-50:]}")

# Check for common issues issues = []

# Single quotes if "'" in json_string and '"' not in json_string: issues.append("Uses single quotes instead of double quotes")

# Trailing comma if json_string.strip().endswith(','): issues.append("Possible trailing comma")

# Unbalanced brackets open_braces = json_string.count('{') close_braces = json_string.count('}') if open_braces != close_braces: issues.append(f"Unbalanced braces: {open_braces} open, {close_braces} close")

open_brackets = json_string.count('[') close_brackets = json_string.count(']') if open_brackets != close_brackets: issues.append(f"Unbalanced brackets: {open_brackets} open, {close_brackets} close")

for issue in issues: print(f"Potential issue: {issue}")

return issues ```

Step 3: Use JSON Validator

```bash # Online validators # https://jsonlint.com # https://jsonformatter.curiousconcept.com

# Command line python -m json.tool invalid.json # Shows parse error jq . invalid.json # Alternative validator ```

```python # Python validation import json

def validate_json_file(filepath): """Validate JSON file.""" with open(filepath) as f: content = f.read()

try: json.loads(content) print("JSON is valid") return True except json.JSONDecodeError as e: print(f"Invalid JSON: {e}") return False ```

Solutions

Solution 1: Fix Trailing Commas

```python import json

# Problem: Trailing comma json_string = '{"items": [1, 2, 3,]}' json.loads(json_string) # JSONDecodeError

# Fix: Remove trailing comma json_string = '{"items": [1, 2, 3]}' data = json.loads(json_string) # Works

# Or fix programmatically def remove_trailing_commas(json_string): """Remove trailing commas from JSON string.""" import re # Remove trailing comma before ] or } fixed = re.sub(r',\s*([}]])', r'\1', json_string) return fixed

# Apply fix fixed_string = remove_trailing_commas(json_string) data = json.loads(fixed_string) ```

Solution 2: Fix Single Quotes to Double Quotes

```python import json

# Problem: Single quotes json_string = "{'key': 'value'}" json.loads(json_string) # JSONDecodeError

# Fix: Use double quotes json_string = '{"key": "value"}' data = json.loads(json_string) # Works

# Or convert programmatically def convert_quotes(json_string): """Convert single quotes to double quotes.""" # This is tricky - need to handle escaped quotes import re

# Replace single quotes around keys and values # Be careful not to replace quotes inside strings fixed = json_string.replace("'", '"')

# This simple approach may fail for complex cases # Better: use ast.literal_eval for Python-style dict return fixed

# Alternative: Use ast for Python-style strings import ast python_dict = ast.literal_eval("{'key': 'value'}") # Then convert to JSON properly json_string = json.dumps(python_dict) ```

Solution 3: Fix Missing Values

```python import json

# Problem: Key without value json_string = '{"key": }' json.loads(json_string) # JSONDecodeError

# Fix: Add value json_string = '{"key": null}' # Use null for missing value data = json.loads(json_string)

# Or empty string json_string = '{"key": ""}' data = json.loads(json_string) ```

Solution 4: Handle Extra Data

```python import json

# Problem: Multiple JSON objects json_string = '{"a": 1}{"b": 2}' json.loads(json_string) # JSONDecodeError: Extra data

# Fix: Use JSONDecoder with raw_decode decoder = json.JSONDecoder() data, end = decoder.raw_decode(json_string) print(data) # {"a": 1} remaining = json_string[end:] print(remaining) # {"b": 2}

# Parse multiple objects def parse_multiple_json(json_string): """Parse multiple JSON objects from string.""" decoder = json.JSONDecoder() objects = [] idx = 0

while idx < len(json_string): # Skip whitespace while idx < len(json_string) and json_string[idx].isspace(): idx += 1

if idx >= len(json_string): break

obj, end = decoder.raw_decode(json_string[idx:]) objects.append(obj) idx += end

return objects

objects = parse_multiple_json('{"a": 1}{"b": 2}{"c": 3}') print(objects) # [{'a': 1}, {'b': 2}, {'c': 3}] ```

Solution 5: Fix Control Characters

```python import json

# Problem: Unescaped control characters json_string = '{"text": "line1\nline2"}' json.loads(json_string) # JSONDecodeError: Invalid control character

# Fix: Escape control characters json_string = '{"text": "line1\\nline2"}' data = json.loads(json_string) # Works print(data['text']) # "line1\nline2" (actual newline in value)

# Or when creating JSON, let json.dumps handle it data = {"text": "line1\nline2"} json_string = json.dumps(data) # Properly escapes print(json_string) # {"text": "line1\nline2"}

# Manual escape for common characters def escape_json_string(s): """Escape string for JSON.""" escape_map = { '\n': '\\n', '\r': '\\r', '\t': '\\t', '\b': '\\b', '\f': '\\f', '"': '\\"', '\\': '\\\\', } for char, escaped in escape_map.items(): s = s.replace(char, escaped) return s ```

Solution 6: Handle Encoding Issues

```python import json

# Problem: Non-UTF-8 encoding json_string = '{"key": "value"}'.encode('latin-1') json.loads(json_string) # May fail or decode incorrectly

# Fix: Ensure UTF-8 encoding json_string = '{"key": "value"}'.encode('utf-8') data = json.loads(json_string) # Works

# Or decode first json_bytes = b'{"key": "value"}' json_string = json_bytes.decode('utf-8') data = json.loads(json_string)

# Handle mixed encoding def safe_json_loads(content): """Load JSON with encoding handling.""" if isinstance(content, bytes): # Try UTF-8 first try: content = content.decode('utf-8') except UnicodeDecodeError: # Try other encodings content = content.decode('utf-8', errors='replace')

return json.loads(content) ```

Solution 7: Fix File Reading Issues

```python import json

# Problem: Reading multiple JSON objects from file with open('data.json') as f: data = json.load(f) # Fails if file has multiple objects

# Fix: Read line by line if each line is JSON def read_json_lines(filepath): """Read JSON objects from file (one per line).""" objects = [] with open(filepath) as f: for line in f: line = line.strip() if line: objects.append(json.loads(line)) return objects

# Fix: Use raw_decode for concatenated JSON def read_concatenated_json(filepath): """Read multiple concatenated JSON objects.""" with open(filepath) as f: content = f.read()

return parse_multiple_json(content) ```

Solution 8: Robust JSON Parsing

```python import json import re

def robust_json_parse(json_string, fix_trailing_commas=True, fix_quotes=False): """Parse JSON with automatic fixes.""" original = json_string

if fix_trailing_commas: json_string = re.sub(r',\s*([}]])', r'\1', json_string)

if fix_quotes: # Be careful with this - can break valid JSON pass

try: return json.loads(json_string) except json.JSONDecodeError as e: # Try to provide helpful message print(f"Could not fix JSON automatically") print(f"Original error: {e.msg} at position {e.pos}")

# Show problematic area start = max(0, e.pos - 30) end = min(len(original), e.pos + 30) print(f"Context: ...{original[start:end]}...")

raise

# Usage try: data = robust_json_parse('{"items": [1, 2, 3,]}') print(data) # {'items': [1, 2, 3]} except json.JSONDecodeError: # Handle manually pass ```

JSON Validation Patterns

Pre-validate JSON

```python import json

def safe_json_parse(content, default=None): """Parse JSON safely with default fallback.""" try: return json.loads(content) except (json.JSONDecodeError, TypeError) as e: print(f"JSON parse error: {e}") return default

# Usage data = safe_json_parse(api_response, default={}) if data is None: print("Failed to parse JSON, using empty object") data = {} ```

Validate JSON Schema

```python import json try: from jsonschema import validate except ImportError: pass # jsonschema not installed

def validate_with_schema(json_data, schema): """Validate JSON against schema.""" try: validate(instance=json_data, schema=schema) return True except Exception as e: print(f"Schema validation error: {e}") return False

# Schema example user_schema = { "type": "object", "required": ["name", "email"], "properties": { "name": {"type": "string"}, "email": {"type": "string", "format": "email"}, "age": {"type": "integer", "minimum": 0} } }

data = {"name": "Alice", "email": "alice@example.com"} if validate_with_schema(data, user_schema): print("Valid user data") ```

Fix API Response JSON

```python import json import requests

def safe_api_request(url): """Request API with JSON error handling.""" response = requests.get(url)

# Check response content content = response.text

# Pre-process content = content.strip()

# Try parsing try: return json.loads(content) except json.JSONDecodeError as e: print(f"API returned invalid JSON") print(f"Status code: {response.status_code}") print(f"Content preview: {content[:100]}...") print(f"Parse error: {e}")

# Maybe it's not JSON at all if content.startswith('<'): print("Response appears to be HTML, not JSON")

return None ```

Common JSON Mistakes

```python # Common mistakes and fixes

# 1. Trailing comma # WRONG: {"items": [1, 2, 3,]} # RIGHT: {"items": [1, 2, 3]}

# 2. Single quotes # WRONG: {'key': 'value'} # RIGHT: {"key": "value"}

# 3. Unquoted keys # WRONG: {key: "value"} # RIGHT: {"key": "value"}

# 4. Comments (JSON doesn't support comments) # WRONG: {"key": "value" /* comment */} # RIGHT: {"key": "value"}

# 5. Undefined/None should be null # WRONG: {"value": undefined} # RIGHT: {"value": null}

# 6. Missing closing brackets # WRONG: {"key": "value" # RIGHT: {"key": "value"}

# 7. Numbers without quotes are fine # RIGHT: {"count": 42, "price": 19.99}

# 8. Booleans without quotes # RIGHT: {"active": true, "deleted": false} ```

Prevention Tips

  1. 1.Use json.dumps() for creating JSON - handles escaping properly
  2. 2.Validate input before parsing
  3. 3.Handle errors gracefully with defaults
  4. 4.Check encoding when reading from files/network
  5. 5.Use schema validation for critical data

```python # Good pattern: Safe JSON handling import json

def process_json_input(content): """Process JSON input safely.""" # Ensure string if isinstance(content, bytes): content = content.decode('utf-8')

# Strip whitespace content = content.strip()

# Validate structure hints if not content: return {}

if content[0] not in '{[': raise ValueError("JSON must start with { or [")

# Parse try: return json.loads(content) except json.JSONDecodeError as e: # Log error with context print(f"JSON error at position {e.pos}: {e.msg}") raise ValueError(f"Invalid JSON: {e.msg}") ```

  • TypeError - Input not string or bytes
  • ValueError - Similar errors in older Python versions
  • UnicodeDecodeError - Encoding issues before parsing
  • FileNotFoundError - When loading from missing file