82 lines
2.4 KiB
Python
82 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
JSON Validator - Validates JSON files with detailed error reporting.
|
|
Usage: python3 json_validator.py <file.json> [file2.json ...]
|
|
"""
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
|
|
def validate_json_file(filepath: str) -> dict[str, Any]:
|
|
"""Validate a JSON file and return analysis results."""
|
|
result = {
|
|
"file": filepath,
|
|
"valid": False,
|
|
"error": None,
|
|
"type": None,
|
|
"size": None,
|
|
"line_count": None,
|
|
"structure": None
|
|
}
|
|
|
|
path = Path(filepath)
|
|
if not path.exists():
|
|
result["error"] = f"File not found: {filepath}"
|
|
return result
|
|
|
|
result["size"] = path.stat().st_size
|
|
|
|
try:
|
|
with open(path, 'r', encoding='utf-8') as f:
|
|
content = f.read()
|
|
result["line_count"] = content.count('\n') + 1
|
|
|
|
data = json.loads(content)
|
|
result["valid"] = True
|
|
result["type"] = type(data).__name__
|
|
|
|
if isinstance(data, dict):
|
|
result["structure"] = f"Object with {len(data)} keys"
|
|
elif isinstance(data, list):
|
|
result["structure"] = f"Array with {len(data)} elements"
|
|
else:
|
|
result["structure"] = f"Scalar value: {type(data).__name__}"
|
|
|
|
except json.JSONDecodeError as e:
|
|
result["error"] = f"Line {e.lineno}, Column {e.colno}: {e.msg}"
|
|
except UnicodeDecodeError as e:
|
|
result["error"] = f"Encoding error: {e.reason}"
|
|
except Exception as e:
|
|
result["error"] = f"Unexpected error: {e}"
|
|
|
|
return result
|
|
|
|
|
|
def main():
|
|
if len(sys.argv) < 2:
|
|
print("Usage: python3 json_validator.py <file.json> [file2.json ...]")
|
|
print("\nValidates JSON files with detailed error reporting.")
|
|
sys.exit(1)
|
|
|
|
files = sys.argv[1:]
|
|
results = [validate_json_file(f) for f in files]
|
|
|
|
for r in results:
|
|
status = "✓ VALID" if r["valid"] else "✗ INVALID"
|
|
print(f"\n{status}: {r['file']}")
|
|
|
|
if r["valid"]:
|
|
print(f" Type: {r['type']}")
|
|
print(f" Structure: {r['structure']}")
|
|
print(f" Size: {r['size']} bytes, {r['line_count']} lines")
|
|
else:
|
|
print(f" Error: {r['error']}")
|
|
|
|
# Exit with error code if any file is invalid
|
|
sys.exit(0 if all(r["valid"] for r in results) else 1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main() |