Read a JSON File in Python: json.load(), json.loads(), and More
To read a JSON file in Python, open the file with open() and pass the file object to json.load(). That returns a Python dict or list you can use immediately. Python's built-in json module handles everything — no extra packages needed.
Need to inspect or fix a JSON file before loading it? Jsonic's JSON Formatter validates and pretty-prints any JSON instantly.
Format & Validate JSONjson.load() — the standard way to read a JSON file
json.load() reads from a file object. Wrap the open() call in a with block so the file is closed automatically, even if an error occurs. Always specify encoding='utf-8' to handle non-ASCII characters correctly.
import json
with open('data.json', 'r', encoding='utf-8') as f:
data = json.load(f)
print(data['name']) # access any top-level key
print(type(data)) # <class 'dict'> or <class 'list'>If the file contains a JSON array at the top level, data will be a Python list. If it contains a JSON object, data will be a dict.
json.loads() — parse JSON from a string or variable
json.loads() (note the s for "string") deserializes a JSON string already in memory. Use it when JSON arrives as an API response body, a command-line argument, or any variable — not from a file path.
import json
raw = '{"name": "Alice", "age": 30}'
data = json.loads(raw)
print(data['age']) # 30
print(data['name']) # Alicejson.loads() also accepts bytes and bytearray, so you can pass a raw HTTP response body directly without decoding it first.
json.load vs json.loads — comparison
json.load() | json.loads() | |
|---|---|---|
| Input type | File object (open file handle) | String, bytes, or bytearray |
| Memory | Reads from disk via file handle | Entire string must be in memory |
| Typical use | Config files, data files on disk | API responses, CLI args, test fixtures |
| Requires open() | Yes | No |
Both functions return the same Python types. The only difference is where the raw JSON text comes from.
Error handling — FileNotFoundError and JSONDecodeError
Two exceptions can occur when reading a JSON file: FileNotFoundError if the path does not exist, and json.JSONDecodeError if the file contains malformed JSON. JSONDecodeError exposes .msg, .lineno, and .colno so you can point directly to the problem.
import json
def read_json(path: str) -> dict:
try:
with open(path, 'r', encoding='utf-8') as f:
return json.load(f)
except FileNotFoundError:
raise FileNotFoundError(f"File not found: {path}")
except json.JSONDecodeError as e:
raise ValueError(
f"Invalid JSON in {path}: {e.msg} at line {e.lineno}, col {e.colno}"
)Wrapping the error with a meaningful message saves time when debugging configuration files loaded at startup. Never let a bare JSONDecodeError bubble up to end users.
pathlib — modern file reading in Python 3.4+
The pathlib.Path class provides an object-oriented interface to file paths. Path.read_text() reads the file as a string, which you then pass to json.loads(). This style avoids the explicit open() context manager and is especially clean in scripts and tests.
import json
from pathlib import Path
path = Path('data/config.json')
data = json.loads(path.read_text(encoding='utf-8'))
# Path objects work with directories too
config_dir = Path(__file__).parent / 'config'
settings = json.loads((config_dir / 'settings.json').read_text(encoding='utf-8'))Path objects compose with / for cross-platform path building, so this pattern works identically on Windows and Unix.
Writing JSON back to a file with json.dump()
json.dump() is the inverse of json.load(): it serializes a Python object to a file. Use indent=2 for human-readable output and ensure_ascii=False to preserve Unicode characters like accented letters or emoji.
import json
data = {'name': 'Alice', 'scores': [95, 87, 92]}
with open('output.json', 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
# output.json:
# {
# "name": "Alice",
# "scores": [
# 95,
# 87,
# 92
# ]
# }To get a JSON string instead of writing to a file, use json.dumps() (with an s). Both functions accept the same keyword arguments.
Python type mapping from JSON
json.load() converts each JSON type to its Python equivalent automatically. The table below shows the full mapping.
| JSON type | Python type | Example |
|---|---|---|
object {} | dict | {"key": "value"} → {"key": "value"} |
array [] | list | [1, 2, 3] → [1, 2, 3] |
string "" | str | "hello" → 'hello' |
| number (integer) | int | 42 → 42 |
| number (float) | float | 3.14 → 3.14 |
true | True | true → True |
false | False | false → False |
null | None | null → None |
Typed JSON with dataclasses (Python 3.7+)
For structured config files, map the JSON dict directly into a @dataclass. This gives you IDE autocompletion and catches missing fields at load time instead of at the call site.
import json
from dataclasses import dataclass
@dataclass
class Config:
host: str
port: int
debug: bool
def read_config(path: str) -> Config:
with open(path, 'r', encoding='utf-8') as f:
raw = json.load(f)
return Config(**raw)
# Usage:
cfg = read_config('config.json')
print(cfg.host) # typed access, IDE-friendly
print(cfg.port)Config(**raw) will raise a TypeError if the JSON is missing a required field or contains an unexpected key, which gives you early validation for free. For deeper nested structures, consider dataclasses with __post_init__, or a library like dacite or pydantic.
Large JSON files — streaming with ijson
json.load() loads the entire file into memory at once. For files that are hundreds of megabytes or larger, that causes out-of-memory errors. The third-party library ijson parses JSON incrementally, yielding items one at a time from a stream.
# Install first: pip install ijson
import ijson
with open('large.json', 'rb') as f:
# 'items.item' means: iterate over each element of the "items" array
for record in ijson.items(f, 'items.item'):
process(record) # handle one record at a timeOpen the file in binary mode ('rb') when using ijson; it handles encoding internally. The second argument to ijson.items() is a dot-path prefix that identifies which part of the JSON tree to stream.
If your large file is a JSON Lines file (one JSON object per line), you do not need ijson. Read line by line and call json.loads() on each:
import json
with open('records.jsonl', 'r', encoding='utf-8') as f:
for line in f:
record = json.loads(line)
process(record)Reading JSON from a URL in Python
When JSON comes from an HTTP endpoint rather than a file, use the requests library. Its response.json() method calls json.loads() internally and raises requests.JSONDecodeError on malformed responses.
import requests
response = requests.get('https://api.example.com/data')
response.raise_for_status() # raises HTTPError on 4xx/5xx
data = response.json() # dict or list
print(data['results'])Without the requests library, use the standard urllib.request module:
import json
import urllib.request
with urllib.request.urlopen('https://api.example.com/data') as response:
data = json.load(response) # response is a file-like objectFrequently asked questions
What is the difference between json.load() and json.loads() in Python?
json.load() takes a file object — you pass it an open file handle and it reads from disk. json.loads() takes a string, bytes, or bytearray already in memory. Rule of thumb: if you have a file path, use open() and json.load(). If you have a JSON string in a variable, use json.loads().
How do I read a JSON file in Python 3?
Import json, open the file with open('data.json', 'r', encoding='utf-8'), and call json.load(f) on the file handle. The entire JSON value — dict, list, string, number, or boolean — is returned as the equivalent Python type. No third-party packages are needed.
How do I handle errors when reading a JSON file in Python?
Wrap the call in a try/except block catching FileNotFoundError (file missing) and json.JSONDecodeError (malformed content). Access e.lineno and e.colno on the JSONDecodeError to show the exact location of the syntax error.
How do I read a nested JSON file in Python?
json.load() recursively converts nested JSON objects to dicts and nested JSON arrays to lists. Access nested values with chained subscripts: data['user']['address']['city']. For optional keys that might be absent, use data.get('user', ).get('address', ).get('city') to avoid KeyError.
How do I write Python data to a JSON file?
Use json.dump(data, f, indent=2, ensure_ascii=False) inside a with open('output.json', 'w', encoding='utf-8') as f: block. indent=2 produces human-readable output. ensure_ascii=False preserves non-ASCII characters like accents or CJK text instead of escaping them.
How do I read JSON from a URL in Python?
Install requests (pip install requests), fetch the URL with requests.get(url), and call response.json(). For the standard library only, open the URL with urllib.request.urlopen(url) and pass the response (a file-like object) to json.load().
Validate your JSON before loading it
Catching a JSONDecodeError is easier when you know exactly what's wrong. Paste your JSON into Jsonic's JSON Formatter to highlight syntax errors with line numbers before running your Python script.