#!/usr/bin/env python3 import argparse import json import sys from typing import Any, TextIO def pretty_print(source: TextIO, destination: TextIO) -> None: """Read JSON from source and write a consistently formatted version.""" data: Any = json.load(source) json.dump(data, destination, indent=2, ensure_ascii=False) destination.write("\n") def _run_tests() -> None: """Run a couple of lightweight sanity checks.""" from io import StringIO output = StringIO() pretty_print(StringIO('{"name":"Ada","active":true}'), output) assert output.getvalue() == ( '{\n "name": "Ada",\n "active": true\n}\n' ) output = StringIO() pretty_print(StringIO("[1,null]"), output) assert output.getvalue() == "[\n 1,\n null\n]\n" def main() -> int: parser = argparse.ArgumentParser(description="Pretty-print JSON.") parser.add_argument( "file", nargs="?", type=argparse.FileType("r", encoding="utf-8"), default=sys.stdin, help="JSON file (defaults to standard input)", ) parser.add_argument( "--test", action="store_true", help="run built-in tests", ) args = parser.parse_args() if args.test: _run_tests() return 0 try: pretty_print(args.file, sys.stdout) except json.JSONDecodeError as error: print(f"Invalid JSON: {error}", file=sys.stderr) return 1 finally: if args.file is not sys.stdin: args.file.close() return 0 if __name__ == "__main__": raise SystemExit(main())