#!/usr/bin/env python3 """A tiny JSON pretty-printer.""" import argparse import json import sys from pathlib import Path from typing import Any, Sequence def pretty_json(text: str, *, indent: int = 2, sort_keys: bool = False) -> str: """Parse JSON text and return a consistently formatted representation.""" value: Any = json.loads(text) return json.dumps(value, indent=indent, sort_keys=sort_keys, ensure_ascii=False) def main(argv: Sequence[str] | None = None) -> int: parser = argparse.ArgumentParser(description="Pretty-print JSON.") parser.add_argument("file", nargs="?", type=Path, help="input file; defaults to stdin") parser.add_argument("-i", "--indent", type=int, default=2) parser.add_argument("-s", "--sort-keys", action="store_true") args = parser.parse_args(argv) try: text = args.file.read_text(encoding="utf-8") if args.file else sys.stdin.read() print(pretty_json(text, indent=args.indent, sort_keys=args.sort_keys)) except (OSError, json.JSONDecodeError) as error: print(f"error: {error}", file=sys.stderr) return 1 return 0 # Small pytest-compatible checks. def test_pretty_json_indents_nested_values() -> None: assert pretty_json('{"a":[1,true]}') == '{\n "a": [\n 1,\n true\n ]\n}' def test_pretty_json_sorts_keys() -> None: assert pretty_json('{"z":1,"a":2}', sort_keys=True).index('"a"') < pretty_json( '{"z":1,"a":2}', sort_keys=True ).index('"z"') if __name__ == "__main__": raise SystemExit(main())