Files
troupe-standup/wizard-work/spark/json_formatter.py
T

76 lines
2.4 KiB
Python

#!/usr/bin/env python3
"""
JSON Formatter Utility
Validates and pretty-prints JSON files with customizable indentation.
Supports file input or stdin piping.
Usage:
json_formatter.py <input.json> [indent] # format file
echo '{}' | json_formatter.py # format from stdin
json_formatter.py invalid.json # validate (exit 1 if invalid)
"""
import json
import sys
from pathlib import Path
def format_json(input_path: str = None, content: str = None, indent: int = 2) -> str:
"""
Read JSON from file or string, validate it, and return formatted output.
Args:
input_path: Path to the JSON file (mutually exclusive with content)
content: Raw JSON string content (mutually exclusive with input_path)
indent: Number of spaces for indentation (default: 2)
Returns:
Formatted JSON string
Raises:
FileNotFoundError: If file doesn't exist
json.JSONDecodeError: If file contains invalid JSON
"""
if content is None:
path = Path(input_path)
if not path.exists():
raise FileNotFoundError(f"File not found: {input_path}")
with open(path, 'r', encoding='utf-8') as f:
data = json.load(f)
else:
data = json.loads(content)
# Validate by re-serializing
json.dumps(data) # Will raise if data contains non-serializable types
return json.dumps(data, indent=indent, ensure_ascii=False, sort_keys=True)
def main():
input_file = sys.argv[1] if len(sys.argv) > 1 else None
indent = int(sys.argv[2]) if len(sys.argv) > 2 else 2
try:
if input_file:
formatted = format_json(input_path=input_file, indent=indent)
else:
# Read from stdin
content = sys.stdin.read()
if not content.strip():
print("Error: No input provided", file=sys.stderr)
sys.exit(1)
formatted = format_json(content=content, indent=indent)
print(formatted)
sys.exit(0)
except FileNotFoundError as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(2)
except json.JSONDecodeError as e:
print(f"JSON Error: {e.msg} at line {e.lineno}, column {e.colno}", file=sys.stderr)
sys.exit(3)
except Exception as e:
print(f"Unexpected error: {e}", file=sys.stderr)
sys.exit(4)
if __name__ == "__main__":
main()