Files

79 lines
2.5 KiB
Python

#!/usr/bin/env python3
"""JSON Schema Validator - validates JSON files against schema and outputs machine-readable report."""
import json
import sys
from pathlib import Path
from typing import Any
def validate_json_schema(data: dict, schema: dict) -> list[str]:
"""Validate a JSON dict against a schema. Returns list of errors."""
errors = []
if not isinstance(data, dict):
return ["Root must be an object"]
if "properties" not in schema:
return []
# Check required fields
for required in schema.get("required", []):
if required not in data:
errors.append(f"Missing required field: '{required}'")
for prop, prop_schema in schema.get("properties", {}).items():
if prop in data:
expected_type = prop_schema.get("type")
if expected_type:
type_map = {"string": str, "number": (int, float), "integer": int, "boolean": bool, "array": list, "object": dict}
expected_py = type_map.get(expected_type)
if expected_py and not isinstance(data[prop], expected_py):
actual_type = type(data[prop]).__name__
errors.append(f"Property '{prop}' expected {expected_type}, got {actual_type}")
return errors
def main():
if len(sys.argv) < 3:
print(json.dumps({"error": "Usage: json_validator.py <json_file> <schema_file>"}))
sys.exit(1)
json_path = Path(sys.argv[1])
schema_path = Path(sys.argv[2])
if not json_path.exists():
print(json.dumps({"valid": False, "errors": [f"File not found: {json_path}"]}))
sys.exit(1)
if not schema_path.exists():
print(json.dumps({"valid": False, "errors": [f"Schema not found: {schema_path}"]}))
sys.exit(1)
try:
with open(json_path) as f:
data = json.load(f)
except json.JSONDecodeError as e:
print(json.dumps({"valid": False, "errors": [f"Invalid JSON: {e}"]}))
sys.exit(1)
try:
with open(schema_path) as f:
schema = json.load(f)
except json.JSONDecodeError as e:
print(json.dumps({"valid": False, "errors": [f"Invalid schema JSON: {e}"]}))
sys.exit(1)
errors = validate_json_schema(data, schema)
result = {
"valid": len(errors) == 0,
"errors": errors,
"file": str(json_path),
"schema": str(schema_path)
}
print(json.dumps(result))
sys.exit(0 if result["valid"] else 1)
if __name__ == "__main__":
main()