from __future__ import annotations from typing import Any, Dict, List, Tuple from jsonschema import Draft202012Validator, FormatChecker from jsonschema.exceptions import ValidationError from .jsonpath_utils import path_to_jsonpath def _to_path_tokens(error: ValidationError) -> List[str]: tokens: List[str] = [] # instance path → tokens for p in error.path: if isinstance(p, int): tokens.append(f"[{p}]") else: tokens.append(f".{p}") return tokens def _error_to_dict(error: ValidationError) -> Dict[str, Any]: tokens = _to_path_tokens(error) return { "message": error.message, "validator": error.validator, "validator_value": error.validator_value, "jsonpath": path_to_jsonpath(tokens), "path_tokens": tokens, "schema_path": list(error.schema_path), } def validate_with_jsonschema( schema: Dict[str, Any], payload: Any ) -> Tuple[bool, List[dict]]: validator = Draft202012Validator(schema, format_checker=FormatChecker()) errors = sorted(validator.iter_errors(payload), key=lambda e: list(e.path)) if not errors: return True, [] return False, [_error_to_dict(e) for e in errors]