You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
suricata/scripts/schema-sort.py

125 lines
3.9 KiB
Python

#!/usr/bin/env python3
#
# Script to sort or just check that properties are in alphabetic order
import json
import sys
import argparse
from collections import OrderedDict
def sort_properties(obj, path=""):
"""Recursively sort 'properties' keys in a JSON schema object."""
if isinstance(obj, dict):
new_obj = OrderedDict()
for key, value in obj.items():
current_path = f"{path}.{key}" if path else key
if key == "properties" and isinstance(value, dict):
sorted_properties = OrderedDict(sorted(value.items()))
new_obj[key] = sorted_properties
for prop_key, prop_value in sorted_properties.items():
new_obj[key][prop_key] = sort_properties(
prop_value, f"{current_path}.{prop_key}"
)
else:
new_obj[key] = sort_properties(value, current_path)
return new_obj
elif isinstance(obj, list):
return [sort_properties(item, f"{path}[{i}]") for i, item in enumerate(obj)]
else:
return obj
def check_properties_sorted(obj, path=""):
"""Check if all 'properties' keys have their contents sorted alphabetically."""
errors = []
if isinstance(obj, dict):
for key, value in obj.items():
current_path = f"{path}.{key}" if path else key
if key == "properties" and isinstance(value, dict):
keys_list = list(value.keys())
sorted_keys = sorted(keys_list)
if keys_list != sorted_keys:
errors.append(f"Properties not sorted at path: {current_path}")
errors.append(f" Current order: {keys_list}")
errors.append(f" Should be: {sorted_keys}")
for prop_key, prop_value in value.items():
errors.extend(
check_properties_sorted(
prop_value, f"{current_path}.{prop_key}"
)
)
else:
errors.extend(check_properties_sorted(value, current_path))
elif isinstance(obj, list):
for i, item in enumerate(obj):
errors.extend(check_properties_sorted(item, f"{path}[{i}]"))
return errors
def main():
parser = argparse.ArgumentParser(
description="Sort JSON schema properties alphabetically"
)
parser.add_argument("schema_file", help="Path to the JSON schema file")
parser.add_argument(
"--check",
action="store_true",
help="Check if properties are sorted (exit 1 if not)",
)
parser.add_argument(
"--in-place",
action="store_true",
help="Sort the file in place (only if not in check mode)",
)
args = parser.parse_args()
try:
with open(args.schema_file, "r") as f:
schema = json.load(f, object_pairs_hook=OrderedDict)
except Exception as e:
print(f"Error reading schema file: {e}", file=sys.stderr)
sys.exit(1)
if args.check:
errors = check_properties_sorted(schema)
if errors:
print("Schema properties are not sorted!", file=sys.stderr)
for error in errors:
print(error, file=sys.stderr)
sys.exit(1)
else:
print("Schema properties are properly sorted.")
sys.exit(0)
else:
sorted_schema = sort_properties(schema)
if args.in_place:
try:
with open(args.schema_file, "w") as f:
json.dump(sorted_schema, f, indent=4)
f.write("\n")
print(f"Sorted schema written to {args.schema_file}")
except Exception as e:
print(f"Error writing schema file: {e}", file=sys.stderr)
sys.exit(1)
else:
print(json.dumps(sorted_schema, indent=4))
if __name__ == "__main__":
main()