parse_json with positional error messages
Python
"""Decode JSON from strings or files and report exactly where it broke."""
import json
from pathlib import Path
from typing import Any
class JSONInputError(ValueError):
"""Raised when JSON text cannot be decoded; message includes position."""
def _position(exc: json.JSONDecodeError, source: str) -> str:
return f"{source}: {exc.msg} (line {exc.lineno}, column {exc.colno})"
def parse_json(text: str, *, source: str = "<string>") -> Any:
"""Decode text, mapping whitespace-only and broken input to JSONInputError."""
if not text.strip():
raise JSONInputError(f"{source}: document is empty")
try:
return json.loads(text)
except json.JSONDecodeError as exc:
raise JSONInputError(_position(exc, source)) from exc
def load_json_file(path: str | Path) -> Any:
"""Read a UTF-8 file (BOM allowed) and decode it with file context."""
path = Path(path)
try:
raw = path.read_text(encoding="utf-8-sig")
except OSError as exc:
raise JSONInputError(f"{path}: cannot read ({exc.strerror})") from exc
return parse_json(raw, source=str(path))