Skip to content
Merged
Show file tree
Hide file tree
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
56 changes: 19 additions & 37 deletions samples/py/json_structure_instance_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,28 @@ class JSONStructureInstanceValidator:
"""
ABSOLUTE_URI_REGEX = re.compile(r'^[a-zA-Z][a-zA-Z0-9+\-.]*://')

def __init__(self, root_schema, allow_import=False, import_map=None, extended=False):
def __init__(self, root_schema, allow_import=False, import_map=None, extended=False, external_schemas=None):
"""
Initializes the validator.
:param root_schema: The JSON Structure (as dict).
:param allow_import: Enables processing of $import/$importdefs.
:param import_map: Dict mapping URIs to local filenames.
:param extended: Enable extended validation features.
:param external_schemas: List of schema dicts to use for resolving imports by $id.
Each schema should have a '$id' field matching the import URI.
"""
self.root_schema = root_schema
self.errors = []
self.allow_import = allow_import
self.import_map = import_map if import_map is not None else {}
self.extended = extended
self.enabled_extensions = set()
# Build lookup for external schemas by $id
self.external_schemas = {}
if external_schemas:
for schema in external_schemas:
if isinstance(schema, dict) and "$id" in schema:
self.external_schemas[schema["$id"]] = schema
# Process $import and $importdefs if enabled. [Metaschema: JSONStructureImport extension constructs]
if self.allow_import:
self._process_imports(self.root_schema, "#")
Expand Down Expand Up @@ -1032,50 +1041,23 @@ def _fetch_external_schema(self, uri):
"""
Fetches an external schema from a URI.
[Metaschema: JSONStructureImport extension resolution]
If the URI is in self.import_map, loads the schema from the specified file.
Otherwise, uses a simulated lookup.
Resolution order:
1. Check external_schemas (pre-loaded schemas matched by $id)
2. Check import_map (URI to file path mapping)
"""
# First check sideloaded schemas by $id
if uri in self.external_schemas:
return self.external_schemas[uri]
# Then check import_map for file paths
if uri in self.import_map:
try:
with open(self.import_map[uri], "r", encoding="utf-8") as f:
return json.load(f)
except Exception as e:
self.errors.append(f"Failed to load imported schema from {self.import_map[uri]}: {e}")
return None
SIMULATED_SCHEMAS = {
"https://example.com/people.json": {
"$schema": "https://json-structure.org/meta/core/v0/#",
"$id": "https://example.com/people.json",
"name": "Person",
"type": "object",
"properties": {
"firstName": {"type": "string"},
"lastName": {"type": "string"},
"address": {"$ref": "#/Address"}
},
"definitions": {
"Address": {
"name": "Address",
"type": "object",
"properties": {
"street": {"type": "string"},
"city": {"type": "string"}
}
}
}
},
"https://example.com/importdefs.json": {
"$schema": "https://json-structure.org/meta/core/v0/#",
"$id": "https://example.com/importdefs.json",
"definitions": {
"LibraryType": {
"name": "LibraryType",
"type": "string"
}
}
}
}
return SIMULATED_SCHEMAS.get(uri)
# URI not found in external_schemas or import_map
return None

def _apply_uses(self, schema, instance):
"""
Expand Down
58 changes: 19 additions & 39 deletions samples/py/json_structure_schema_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,15 @@ class JSONStructureSchemaCoreValidator:
"JSONStructureConditionalComposition", "JSONStructureValidation"
}

def __init__(self, allow_dollar=False, allow_import=False, import_map=None, extended=False):
def __init__(self, allow_dollar=False, allow_import=False, import_map=None, extended=False, external_schemas=None):
"""
Initializes a validator instance.
:param allow_dollar: Boolean flag to allow '$' in property names.
:param allow_import: Boolean flag to enable processing of $import/$importdefs.
:param import_map: Dictionary mapping URI to local filenames.
:param extended: Boolean flag to enable extended validation features.
:param external_schemas: List of schema dicts to use for resolving imports by $id.
Each schema should have a '$id' field matching the import URI.
"""
self.errors = []
self.doc = None
Expand All @@ -87,6 +89,12 @@ def __init__(self, allow_dollar=False, allow_import=False, import_map=None, exte
self.import_map = import_map if import_map is not None else {}
self.extended = extended
self.enabled_extensions = set()
# Build lookup for external schemas by $id
self.external_schemas = {}
if external_schemas:
for schema in external_schemas:
if isinstance(schema, dict) and "$id" in schema:
self.external_schemas[schema["$id"]] = schema
if allow_dollar:
self.identifier_regex = re.compile(r'^[A-Za-z_$][A-Za-z0-9_$]*$')
else:
Expand Down Expand Up @@ -289,51 +297,23 @@ def _process_imports(self, obj, path):
def _fetch_external_schema(self, uri):
"""
Fetches an external schema from a URI.
If a mapping is provided and contains the URI, loads from the given file.
Otherwise, uses a simulated lookup.
"""
Resolution order:
1. Check external_schemas (pre-loaded schemas matched by $id)
2. Check import_map (URI to file path mapping)
"""
# First check sideloaded schemas by $id
if uri in self.external_schemas:
return self.external_schemas[uri]
# Then check import_map for file paths
if uri in self.import_map:
try:
with open(self.import_map[uri], "r", encoding="utf-8") as f:
return json.load(f)
except Exception as e:
self._err(f"Failed to load imported schema from {self.import_map[uri]}: {e}", "#/import")
return None
# Simulated external schemas for testing purposes.
EXTERNAL_SCHEMAS = {
"https://example.com/people.json": {
"$schema": "https://json-structure.org/meta/core/v0/#",
"$id": "https://example.com/people.json",
"name": "Person",
"type": "object",
"properties": {
"firstName": {"type": "string"},
"lastName": {"type": "string"},
"address": {"$ref": "#/definitions/Address"}
},
"definitions": {
"Address": {
"name": "Address",
"type": "object",
"properties": {
"street": {"type": "string"},
"city": {"type": "string"}
}
}
}
},
"https://example.com/address.json": {
"$schema": "https://json-structure.org/meta/core/v0/#",
"$id": "https://example.com/address.json",
"name": "Address",
"type": "object",
"properties": {
"street": {"type": "string"},
"city": {"type": "string"}
}
}
}
return EXTERNAL_SCHEMAS.get(uri)
# URI not found in external_schemas or import_map
return None

def _validate_namespace(self, obj, path):
"""
Expand Down