"""Validate JSON/JSONL with explicit interoperability rules, without rewriting it.""" import argparse import json import sys MAX_BYTES = 1024 * 1024 MAX_ERRORS = 100 MAX_NESTING = 128 class PolicyError(ValueError): pass class NumberLexeme(str): """Keep valid JSON numbers exact while validating; never emit converted data.""" def unique_object(pairs): result = {} for key, value in pairs: if key in result: raise PolicyError("duplicate_key") result[key] = value return result def reject_constant(_): raise PolicyError("non_json_number_constant") def check_nesting(document): depth, quoted, escaped = 0, False, False for char in document: if quoted: if escaped: escaped = False elif char == "\\": escaped = True elif char == '"': quoted = False elif char == '"': quoted = True elif char in "[{": depth += 1 if depth > MAX_NESTING: raise PolicyError("input_nesting_limit") elif char in "]}": depth = max(0, depth - 1) def check_strings(value): pending = [value] while pending: item = pending.pop() if isinstance(item, str): if any(0xD800 <= ord(char) <= 0xDFFF for char in item): raise PolicyError("unpaired_surrogate") elif isinstance(item, dict): pending.extend(item.keys()) pending.extend(item.values()) elif isinstance(item, list): pending.extend(item) def inspect(raw, jsonl=False): result = {"ok": False, "format": "jsonl" if jsonl else "json", "documents": 0, "errors": [], "error_count": 0, "errors_truncated": False} def add_error(error): result["error_count"] += 1 if len(result["errors"]) < MAX_ERRORS: result["errors"].append(error) else: result["errors_truncated"] = True if len(raw) > MAX_BYTES: add_error({"code": "input_too_large"}) return result if raw.startswith(b"\xef\xbb\xbf"): add_error({"code": "utf8_bom_not_allowed"}) return result try: text = raw.decode("utf-8", errors="strict") except UnicodeDecodeError: add_error({"code": "invalid_utf8"}) return result documents = text.split("\n") if jsonl else [text] if jsonl and documents[-1] == "" and text.endswith("\n"): documents.pop() for line, document in enumerate(documents, 1): location = {"line": line} if jsonl else {} try: if jsonl and not document.strip(" \t\r"): raise PolicyError("blank_jsonl_line") check_nesting(document) value = json.loads(document, object_pairs_hook=unique_object, parse_constant=reject_constant, parse_int=NumberLexeme, parse_float=NumberLexeme) check_strings(value) result["documents"] += 1 except PolicyError as error: add_error({**location, "code": str(error)}) except json.JSONDecodeError as error: add_error({**location, "code": "json_syntax", "document_line": error.lineno, "column": error.colno}) except RecursionError: add_error({**location, "code": "parser_depth_limit"}) result["ok"] = not result["errors"] return result def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--jsonl", action="store_true", help="Validate one JSON value per physical line") args = parser.parse_args() result = inspect(sys.stdin.buffer.read(MAX_BYTES + 1), args.jsonl) print(json.dumps(result)) return 0 if result["ok"] else 1 if __name__ == "__main__": raise SystemExit(main())