I have a set of jsonschema compliant documents. Some documents contain references to other documents (via the $ref
attribute). I do not wish to host these documents such that they are accessible at an HTTP URI. As such, all references are relative. All documents live in a local folder structure.
How can I make python-jsonschema
understand to properly use my local file system to load referenced documents?
For instance, if I have a document with filename defs.json
containing some definitions. And I try to load a different document which references it, like:
{
"allOf": [
{"$ref":"defs.json#/definitions/basic_event"},
{
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": ["page_load"]
}
},
"required": ["action"]
}
]
}
I get an error RefResolutionError: <urlopen error [Errno 2] No such file or directory: '/defs.json'>
It may be important that I'm on a linux box.
(I'm writing this as a Q&A because I had a hard time figuring this out and observed other folks having trouble too.)
I had the hardest time figuring out how to do resolve against a set of schemas that $ref
each other (I am new to JSON Schemas). It turns out the key is to create the RefResolver
with a store
that is a dict
which maps from url to schema.
Building on @devin-p's answer:
import json
from jsonschema import RefResolver, Draft7Validator
base = """
{
"$id": "base.schema.json",
"type": "object",
"properties": {
"prop": {
"type": "string"
}
},
"required": ["prop"]
}
"""
extend = """
{
"$id": "extend.schema.json",
"allOf": [
{"$ref": "base.schema.json#"},
{
"properties": {
"extra": {
"type": "boolean"
}
},
"required": ["extra"]
}
]
}
"""
extend_extend = """
{
"$id": "extend_extend.schema.json",
"allOf": [
{"$ref": "extend.schema.json#"},
{
"properties": {
"extra2": {
"type": "boolean"
}
},
"required": ["extra2"]
}
]
}
"""
data = """
{
"prop": "This is the property string",
"extra": true,
"extra2": false
}
"""
schema = json.loads(base)
extendedSchema = json.loads(extend)
extendedExtendSchema = json.loads(extend_extend)
schema_store = {
schema['$id'] : schema,
extendedSchema['$id'] : extendedSchema,
extendedExtendSchema['$id'] : extendedExtendSchema,
}
resolver = RefResolver.from_schema(schema, store=schema_store)
validator = Draft7Validator(extendedExtendSchema, resolver=resolver)
jsonData = json.loads(data)
validator.validate(jsonData)
The above was built with jsonschema==3.2.0
.