]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
schema: add script to check or sort the schema
authorJason Ish <jason.ish@oisf.net>
Sun, 18 May 2025 16:18:03 +0000 (10:18 -0600)
committerVictor Julien <victor@inliniac.net>
Sun, 18 May 2025 19:17:22 +0000 (21:17 +0200)
scripts/schema-sort.py [new file with mode: 0755]

diff --git a/scripts/schema-sort.py b/scripts/schema-sort.py
new file mode 100755 (executable)
index 0000000..5ba8303
--- /dev/null
@@ -0,0 +1,124 @@
+#!/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()