← Back to Blog

How to Parse JSON in Python: Complete Guide

March 9, 2026 8 min read By CodeTidy Team

JSON (JavaScript Object Notation) is the most common data format for APIs, configuration files, and data exchange between systems. Python's built-in json module makes parsing JSON straightforward, but there are several methods and edge cases worth understanding. This guide covers everything you need to know.

Parsing a JSON String with json.loads()

The most common operation is parsing a JSON string into a Python dictionary. Use json.loads() (load-string):

import json

json_string = '{"name": "Alice", "age": 30, "active": true}'
data = json.loads(json_string)

print(data["name"])    # Alice
print(data["age"])     # 30
print(type(data))      # <class 'dict'>

The JSON-to-Python type mapping is intuitive:

JSON TypePython Type
object {}dict
array []list
stringstr
number (int)int
number (float)float
true / falseTrue / False
nullNone

Reading JSON from a File with json.load()

Note the function name difference: json.load() (no "s") reads from a file object, while json.loads() parses a string.

import json

with open("config.json", "r") as f:
    config = json.load(f)

print(config["database"]["host"])  # localhost

Always use a with statement to ensure the file handle is properly closed, even if parsing fails.

Parsing JSON from an API Response

When working with APIs using the requests library, you don't need to call json.loads() manually — the response object has a built-in .json() method:

import requests

response = requests.get("https://api.example.com/users/1")
user = response.json()

print(user["name"])
print(user["email"])

Under the hood, response.json() calls json.loads(response.text) and handles encoding detection automatically.

Converting Python Objects to JSON

The reverse operation uses json.dumps() (dump-string) and json.dump() (dump to file):

import json

data = {
    "name": "Bob",
    "scores": [95, 87, 92],
    "active": True,
    "address": None
}

# To string
json_string = json.dumps(data, indent=2)
print(json_string)

# To file
with open("output.json", "w") as f:
    json.dump(data, f, indent=2)

The indent parameter controls pretty-printing. Use indent=2 or indent=4 for readable output, or omit it for compact single-line JSON.

Handling Common Parsing Errors

Invalid JSON raises a json.JSONDecodeError. Always wrap parsing in a try/except block when handling untrusted input:

import json

def safe_parse(json_string):
    try:
        return json.loads(json_string)
    except json.JSONDecodeError as e:
        print(f"Invalid JSON at line {e.lineno}, column {e.colno}: {e.msg}")
        return None

# Common mistakes that cause errors:
safe_parse("{name: 'Alice'}")       # Keys must be double-quoted
safe_parse("{'name': 'Alice'}")     # Must use double quotes, not single
safe_parse('{"age": 030}')           # No leading zeros on numbers
safe_parse('{"items": [1, 2,]}')     # No trailing commas

Working with Nested JSON

Real-world JSON is often deeply nested. Access values by chaining keys, and use .get() for safe access:

import json

response = '''{
  "data": {
    "users": [
      {"id": 1, "name": "Alice", "address": {"city": "Portland"}},
      {"id": 2, "name": "Bob", "address": null}
    ]
  }
}'''

data = json.loads(response)

# Direct access (raises KeyError if missing)
city = data["data"]["users"][0]["address"]["city"]
print(city)  # Portland

# Safe access with .get() and defaults
for user in data["data"]["users"]:
    address = user.get("address") or {}
    city = address.get("city", "Unknown")
    print(f"{user['name']}: {city}")

Parsing Large JSON Files Efficiently

For very large JSON files (hundreds of MB), loading the entire file into memory may not be practical. Use ijson for streaming/iterative parsing:

# pip install ijson
import ijson

with open("large_data.json", "rb") as f:
    # Parse items from a JSON array one at a time
    for item in ijson.items(f, "records.item"):
        process(item)  # Only one item in memory at a time

For moderately large files (10-100 MB), the built-in json module is usually fine — it's implemented in C and is quite fast.

Custom JSON Encoding and Decoding

Python's json module can't serialize all Python types by default. Dates, sets, and custom objects need a custom encoder:

import json
from datetime import datetime, date

class CustomEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, (datetime, date)):
            return obj.isoformat()
        if isinstance(obj, set):
            return list(obj)
        return super().default(obj)

data = {
    "created": datetime.now(),
    "tags": {"python", "json", "tutorial"}
}

print(json.dumps(data, cls=CustomEncoder, indent=2))

Performance Tips

  • Use orjson for speed — it's 3-10x faster than the standard library for both parsing and serialization. Install with pip install orjson.
  • Avoid repeated parsing — parse once and pass the dictionary around, don't re-parse the same string.
  • Use json.loads() over eval() — never use eval() to parse JSON. It's a serious security vulnerability that allows arbitrary code execution.
  • Validate before processing — use a JSON validator to check your data structure during development.

Quick Reference

OperationMethod
String to dictjson.loads(string)
File to dictjson.load(file_obj)
Dict to stringjson.dumps(dict)
Dict to filejson.dump(dict, file_obj)
Pretty printjson.dumps(dict, indent=2)
Sort keysjson.dumps(dict, sort_keys=True)

JSON parsing in Python is one of those things that's simple 90% of the time and tricky the other 10%. Master the basics covered here, and you'll handle the tricky parts when they come. For quick formatting and validation during development, try our JSON Formatter to instantly beautify and check your JSON output.

Drop file to load