validate_json.py 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import jstyleson
  2. from pathlib import Path
  3. from pprint import pprint
  4. import yaml
  5. import json5
  6. import re
  7. # 'json', 'json5' or 'yaml'
  8. # json: strict, but doesn't preserve line numbers necessarily, since it strips comments before parsing
  9. # json5: strict and preserves line numbers even for files will with line comments
  10. # yaml: less strict, allows e.g. leading zeros
  11. VALIDATION_TYPE = 'json5'
  12. errors = []
  13. for path in sorted(Path('.').glob('**/*.json')):
  14. # because path is an object and not a string
  15. path_str = str(path)
  16. try:
  17. with open(path_str, 'r') as file:
  18. if VALIDATION_TYPE == 'json':
  19. jstyleson.load(file)
  20. if VALIDATION_TYPE == 'json5':
  21. json5.load(file)
  22. elif VALIDATION_TYPE == 'yaml':
  23. file = file.read().replace("\t", " ")
  24. file = file.replace("//", "#")
  25. yaml.safe_load(file)
  26. print(f"Validation of {path_str} succeeded")
  27. except Exception as exc:
  28. print(f"Validation of {path_str} failed")
  29. pprint(exc)
  30. error_pos = path_str
  31. if hasattr(exc, 'pos'):
  32. # https://stackoverflow.com/a/72850269/2278742
  33. error_pos = f"{path_str}:{exc.lineno}:{exc.colno}"
  34. print(error_pos)
  35. # error_msg = "position": position_msg, "exception": exc
  36. if hasattr(exc, 'problem_mark'):
  37. mark = exc.problem_mark
  38. error_pos = f"{path_str}:{mark.line+1}:{mark.column+1}"
  39. print(error_pos)
  40. if VALIDATION_TYPE == 'json5':
  41. pos = re.findall(r'\d+', str(exc))
  42. error_pos = f"{path_str}:{pos[0]}:{pos[-1]}"
  43. errors.append({"error_pos": error_pos, "error_msg": exc})
  44. if errors:
  45. print("Summary of errors:")
  46. pprint(errors)
  47. raise Exception("Not all JSON files are valid")