79 lines
2.5 KiB
Python
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() |