{}JSON-Validator.net
Tutorial · Python · 7 min read

How to Validate JSON in Python

Python's built-in json module makes JSON validation straightforward — wrap json.loads() in a try/except and catch json.JSONDecodeError. This guide covers every approach from a simple one-liner to full schema validation.

The Basic Approach: json.loads + try/except

json.loads() raises json.JSONDecodeError if the input string is not valid JSON. Catch it to validate:

import json

def is_valid_json(text: str) -> bool:
    try:
        json.loads(text)
        return True
    except json.JSONDecodeError:
        return False

# Usage
is_valid_json('{"name": "Alice"}')   # True
is_valid_json("{'name': 'Alice'}")   # False — single quotes
is_valid_json('{"a": 1,}')          # False — trailing comma
is_valid_json('null')               # True — null is valid JSON
is_valid_json('')                   # False — empty string is not valid JSON

Get the Error Message and Line Number

json.JSONDecodeError exposes the lineno, colno, and msg attributes for detailed debugging:

import json
from dataclasses import dataclass
from typing import Any

@dataclass
class JsonResult:
    valid: bool
    data: Any = None
    error: str = None
    line: int = None
    col: int = None

def validate_json(text: str) -> JsonResult:
    try:
        data = json.loads(text)
        return JsonResult(valid=True, data=data)
    except json.JSONDecodeError as e:
        return JsonResult(
            valid=False,
            error=e.msg,
            line=e.lineno,
            col=e.colno,
        )

# Usage
result = validate_json('{"name": "Alice",}')
if not result.valid:
    print(f"Invalid JSON at line {result.line}, col {result.col}: {result.error}")
    # Invalid JSON at line 1, col 18: Expecting property name enclosed in double quotes

Validate a JSON File

Use json.load()(without the 's') to validate directly from a file object. It also raises json.JSONDecodeError on invalid JSON:

import json

def validate_json_file(path: str) -> bool:
    try:
        with open(path, "r", encoding="utf-8") as f:
            json.load(f)
        print(f"✓ {path} is valid JSON")
        return True
    except json.JSONDecodeError as e:
        print(f"✗ {path}: line {e.lineno}, col {e.colno} — {e.msg}")
        return False
    except FileNotFoundError:
        print(f"✗ File not found: {path}")
        return False

# Usage
validate_json_file("config.json")
validate_json_file("data/payload.json")

json.loads vs json.load: Use json.loads(string) for strings and json.load(file) for file objects.

Validate an API Response (requests)

When using the requests library, response.json() handles parsing automatically. But for raw webhook payloads or message queue messages, validate first:

import json
import requests

# Using requests — .json() raises requests.exceptions.JSONDecodeError on failure
response = requests.get("https://api.example.com/data")
try:
    data = response.json()
except requests.exceptions.JSONDecodeError as e:
    print(f"API returned invalid JSON: {e}")

# Raw webhook payload (e.g. from Flask/FastAPI)
def handle_webhook(raw_body: str):
    try:
        payload = json.loads(raw_body)
    except json.JSONDecodeError as e:
        print(f"Invalid webhook JSON at line {e.lineno}: {e.msg}")
        return None
    return payload

Structural Validation with jsonschema

For validating structure — not just syntax — use the jsonschema library. Install it with pip install jsonschema:

import json
import jsonschema
from jsonschema import validate, ValidationError

# Define the expected structure
schema = {
    "type": "object",
    "required": ["name", "age", "email"],
    "properties": {
        "name":  {"type": "string"},
        "age":   {"type": "integer", "minimum": 0},
        "email": {"type": "string", "format": "email"},
    },
    "additionalProperties": False,
}

def validate_user(raw_json: str):
    # Step 1: Check syntax
    try:
        data = json.loads(raw_json)
    except json.JSONDecodeError as e:
        return f"Syntax error at line {e.lineno}: {e.msg}"

    # Step 2: Check structure
    try:
        validate(instance=data, schema=schema)
        return "Valid"
    except ValidationError as e:
        return f"Schema error: {e.message}"

print(validate_user('{"name": "Alice", "age": 30, "email": "[email protected]"}'))
# Valid

print(validate_user('{"name": "Bob", "age": -1, "email": "[email protected]"}'))
# Schema error: -1 is less than the minimum of 0

Python JSON Edge Cases

json.loads('null') returns None
Python maps JSON null to None. json.loads('null') returns None, not the string 'null'. This is valid JSON.
Integers vs. floats
Python preserves the JSON type. json.loads('1') returns int(1) and json.loads('1.0') returns float(1.0). Use json.loads(s, parse_float=Decimal) if you need exact decimal handling.
Non-ASCII characters
json.loads() handles Unicode natively. Escaped sequences like \u0041 are decoded automatically. No extra steps needed for non-ASCII JSON strings.
BOM (Byte Order Mark)
JSON files with a UTF-8 BOM may fail. Open files with encoding='utf-8-sig' to strip the BOM automatically: open(path, encoding='utf-8-sig').
json.JSONDecodeError is a ValueError
json.JSONDecodeError is a subclass of ValueError. Legacy code that catches ValueError will also catch JSON decode errors — but you lose lineno/colno details.

Frequently Asked Questions

How do I check if a string is valid JSON in Python?+

Use json.loads() inside a try/except block. If the string is valid JSON, json.loads() returns the parsed data. If not, it raises json.JSONDecodeError. Example: try: json.loads(s); return True; except json.JSONDecodeError: return False

What exception does Python raise for invalid JSON?+

Python's json module raises json.JSONDecodeError when it encounters invalid JSON. This is a subclass of ValueError. The exception includes the error message, the document being parsed, and the character position (pos) of the error.

How do I get the line number from a JSON error in Python?+

json.JSONDecodeError has a lineno attribute that contains the line number of the error, and a colno attribute for the column. Example: except json.JSONDecodeError as e: print(f'Line {e.lineno}, column {e.colno}: {e.msg}')

What is the difference between json.loads() and json.load() in Python?+

json.loads() (with an 's') parses a JSON string. json.load() (without an 's') reads from a file object. Use json.loads(text) for strings and json.load(file) for files opened with open().

How do I validate JSON against a schema in Python?+

Install the jsonschema library (pip install jsonschema) and use jsonschema.validate(instance, schema). This checks both that the JSON is syntactically valid and that it matches the structure defined by your JSON Schema.

Need to Quickly Check JSON Without Coding?

Use the free online validator — paste JSON and get instant syntax feedback.

Open JSON Validator

Related Guides