Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

draft07 downgrade tool: ensure $schema comes first #33

Merged
merged 1 commit into from
Apr 27, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 19 additions & 12 deletions tools/downgrade_schema_to_draft07.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import argparse
import json
import copy
from typing import Any

import jsonschema

Expand All @@ -30,20 +31,26 @@ def walk_dict(obj, match_key, fn):
def downgrade_schema_to_draft07(root_schema):
''' Downgrades a schema to draft-07 JSON Schema dialect '''

root_schema = copy.deepcopy(root_schema)

schema_key = "$schema"
if root_schema.get(schema_key) == JSON_SCHEMA_DRAFT_07:
print("Schema is already in draft-07 dialect")
return root_schema

# Change dialect declaration
root_schema[schema_key] = JSON_SCHEMA_DRAFT_07
out: dict[str, Any] = {
schema_key: JSON_SCHEMA_DRAFT_07
}

# Copy existing schema without $schema key
root_schema = copy.deepcopy(root_schema)
if schema_key in root_schema:
del root_schema[schema_key]
out.update(root_schema)

# Move all "$defs" to top-level "definitions"
definitions_key = "definitions"
assert definitions_key not in root_schema
root_schema[definitions_key] = definitions = {}
assert definitions_key not in out
out[definitions_key] = definitions = {}

defs_key = "$defs"
id_key = "$id"
Expand All @@ -60,8 +67,8 @@ def move_defs(obj, key, value):
definitions[name] = schema
del obj[defs_key]

walk_dict(root_schema, defs_key, move_defs)
root_schema[definitions_key] = dict(sorted(definitions.items()))
walk_dict(out, defs_key, move_defs)
out[definitions_key] = dict(sorted(definitions.items()))

# Change all "$ref" values to use JSON pointer syntax
ref_key = "$ref"
Expand All @@ -79,7 +86,7 @@ def patch_ref_json_pointer(obj, key, value):
f"in definitions: {', '.join(definitions.keys())}"
obj[key] = new_value

walk_dict(root_schema, ref_key, patch_ref_json_pointer)
walk_dict(out, ref_key, patch_ref_json_pointer)

# Ensure "$ref" is not used alongside other keywords,
# else wrap with "allOf"
Expand All @@ -104,7 +111,7 @@ def patch_ref_alone(obj, key, value):
del obj[k]
obj["allOf"] = all_of

walk_dict(root_schema, ref_key, patch_ref_alone)
walk_dict(out, ref_key, patch_ref_alone)

# Rename "dependentSchemas" to "dependencies"
dependent_schemas_key = "dependentSchemas"
Expand All @@ -116,13 +123,13 @@ def patch_dependent_schemas(obj, key, value):
obj[dependencies_key] = value
del obj[dependent_schemas_key]

walk_dict(root_schema, dependent_schemas_key, patch_dependent_schemas)
walk_dict(out, dependent_schemas_key, patch_dependent_schemas)

# Validate against the draft-07 meta schema
# This will not catch all errors, but it is a good start
jsonschema.Draft7Validator.check_schema(root_schema)
jsonschema.Draft7Validator.check_schema(out)

return root_schema
return out


if __name__ == "__main__":
Expand Down