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

118 lines
3.6 KiB
Python

#!/usr/bin/env python3
"""
JSON Schema Validator CLI
A simple command-line tool to validate JSON files against JSON schemas.
Usage: python json_schema_cli.py <json_file> <schema_file> [--output report.json]
"""
import json
import sys
import argparse
from typing import Any
def load_json(path: str) -> dict | list | None:
"""Load and parse JSON from file path."""
with open(path, 'r') as f:
return json.load(f)
def validate_data(data: Any, schema: dict) -> list[str]:
"""
Validate data against a JSON schema.
Returns list of validation errors (empty if valid).
"""
errors = []
# Basic schema structure check
if '$schema' not in schema and 'type' not in schema:
errors.append("Schema missing required fields ($schema or 'type')")
return errors
# Type validation
if 'type' in schema:
expected_type = schema['type']
actual_type = type(data).__name__
type_map = {
'string': str,
'number': (int, float),
'integer': int,
'boolean': bool,
'array': list,
'object': dict,
'null': type(None)
}
if expected_type in type_map:
expected_py = type_map[expected_type]
if not isinstance(data, expected_py):
errors.append(f"Type mismatch: expected '{expected_type}', got '{actual_type}'")
# Properties validation (for objects)
if isinstance(data, dict) and 'properties' in schema:
props = schema['properties']
for prop, prop_schema in props.items():
if prop in data:
prop_errors = validate_data(data[prop], prop_schema)
for err in prop_errors:
errors.append(f"Property '{prop}': {err}")
elif prop_schema.get('required', False):
errors.append(f"Missing required property: '{prop}'")
# Items validation (for arrays)
if isinstance(data, list) and 'items' in schema:
items_schema = schema['items']
for i, item in enumerate(data):
item_errors = validate_data(item, items_schema)
for err in item_errors:
errors.append(f"Item {i}: {err}")
# Required fields check
if isinstance(data, dict) and 'required' in schema:
for req_field in schema['required']:
if req_field not in data:
errors.append(f"Missing required field: '{req_field}'")
return errors
def main():
parser = argparse.ArgumentParser(description='Validate JSON against a schema')
parser.add_argument('json_file', help='Path to JSON file to validate')
parser.add_argument('schema_file', help='Path to JSON schema file')
parser.add_argument('--output', '-o', help='Output file for validation report')
args = parser.parse_args()
try:
data = load_json(args.json_file)
schema = load_json(args.schema_file)
except FileNotFoundError as e:
print(f"Error: File not found - {e}")
sys.exit(1)
except json.JSONDecodeError as e:
print(f"Error: Invalid JSON - {e}")
sys.exit(1)
errors = validate_data(data, schema)
report = {
'valid': len(errors) == 0,
'errors': errors,
'data_file': args.json_file,
'schema_file': args.schema_file
}
if args.output:
with open(args.output, 'w') as f:
json.dump(report, f, indent=2)
print(f"Report written to {args.output}")
print(json.dumps(report, indent=2))
sys.exit(0 if report['valid'] else 1)
if __name__ == '__main__':
main()