Tutorial

Working with JSON in Python: A Practical Guide for Real Projects

Read, write, validate, transform, and debug JSON safely with Python's standard library, precise number handling, useful CLI commands, and production-minded error handling.

2026-07-2911 min read

Python's built-in json module covers most day-to-day JSON work: reading API fixtures, writing configuration, transforming exports, and diagnosing malformed payloads. The difficult part is rarely the first json.loads call; it is handling encoding, errors, precision, and changing data shapes predictably.

Parse text and handle useful errors

Use json.loads for text already in memory. Catch JSONDecodeError so logs include the exact line and column without exposing the entire payload.

import json

raw = '{"name": "Ada", "active": true}'

try:
    data = json.loads(raw)
except json.JSONDecodeError as exc:
    print(f"Invalid JSON at line {exc.lineno}, column {exc.colno}: {exc.msg}")
    raise

Do not automatically “repair” untrusted input and continue as if nothing happened. Repair can be useful during investigation, but production ingestion should preserve the original input and make every transformation reviewable.

Read and write UTF-8 files

Open text files with an explicit encoding. ensure_ascii=False keeps non-English text readable, while indent=2 produces review-friendly output.

import json
from pathlib import Path

source = Path("input.json")
target = Path("output.json")

with source.open("r", encoding="utf-8") as handle:
    data = json.load(handle)

with target.open("w", encoding="utf-8") as handle:
    json.dump(data, handle, ensure_ascii=False, indent=2)
    handle.write("\n")

For configuration files, write to a temporary file and replace the destination only after serialization succeeds. This avoids leaving a partially written file after a crash.

Preserve decimal precision when it matters

JSON numbers do not define business meaning. Python normally parses decimals as float, which is unsuitable for exact financial calculations. Use Decimal when precision is part of the contract.

import json
from decimal import Decimal

payload = json.loads('{"amount": 19.99}', parse_float=Decimal)
print(payload["amount"] * 3)

Decimal is not JSON serializable by default. Decide whether the external contract expects a decimal string or an integer in minor units, and convert explicitly before writing.

Validate shape before transforming

A parseable value may still have the wrong structure. Check the root type and required fields before iterating.

def normalize_users(value):
    if not isinstance(value, list):
        raise ValueError("Expected a JSON array")

    result = []
    for index, item in enumerate(value):
        if not isinstance(item, dict):
            raise ValueError(f"Item {index} must be an object")
        if "id" not in item or "email" not in item:
            raise ValueError(f"Item {index} is missing id or email")
        result.append({
            "id": str(item["id"]),
            "email": str(item["email"]).strip().lower(),
        })
    return result

For larger contracts, use JSON Schema with a maintained validator library and keep the schema in version control. Syntax validation and contract validation solve different problems.

Transform without silently losing information

When flattening nested JSON for CSV or database import, define how arrays, missing keys, null, and nested objects are represented. Avoid a generic flattening function unless downstream consumers agree on its rules.

def order_row(order):
    customer = order.get("customer") or {}
    return {
        "order_id": order.get("id"),
        "customer_email": customer.get("email"),
        "item_count": len(order.get("items") or []),
        "status": order.get("status", "unknown"),
    }

Keep input and output samples in tests. They document decisions that code alone may not make obvious.

Use the command line for quick checks

Python includes a convenient formatter and syntax checker:

python -m json.tool input.json
python -m json.tool --sort-keys input.json

For a quick visual review, use the JSON Beautifier or JSON Tree Viewer. Remove secrets before pasting data into any tool you do not control; JSON Work performs the transformation locally in the browser, but the surrounding device and browser still need to be trusted.

Production checklist

  • • Set explicit file and HTTP encodings.
  • • Limit accepted payload size and nesting depth at the application boundary.
  • • Log error position and request ID, not secrets or complete payloads.
  • • Distinguish missing values from explicit null.
  • • Use Decimal, strings, or minor units when numeric precision matters.
  • • Validate structure before transformation.
  • • Test empty arrays, Unicode, large integers, invalid JSON, and partial records.

The official json module documentation describes every encoder and decoder option. Start with the standard library, add schema validation when the contract requires it, and keep transformations explicit enough to audit.

Ene Chen

Dedicated to providing developers with the best JSON processing tools

Related Posts

More posts coming soon...

Back to Blog

Related tools

Frequently Asked Questions

Following the blog, topics we cover, and how to suggest guides.

How can I catch new posts?

Bookmark this blog and watch the homepage and tools hub—we surface new guides there. No account or mailing list is required to read articles.

What do you write about?

JSON validation, formatting, conversion, debugging workflows, and JSON Work releases—mapped to what the free on-site tools can do locally in your browser.

Can I suggest a tutorial topic?

Yes. Reach out via the About page or GitHub; we prioritize guides tied to real integration and debugging scenarios.