Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set up local file references in python-jsonschema document?

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.)

like image 416
Chris W. Avatar asked Dec 29 '18 10:12

Chris W.


People also ask

What is JSON Schema module in Python?

jsonschema is an implementation of the JSON Schema specification for Python. validate(instance={"name" : "Eggs", "price" : 34.99}, schema=schema) >>> validate( ... instance={"name" : "Eggs", "price" : "Invalid"}, schema=schema, ... ) It can also be used from console: $ jsonschema --instance sample.json sample.schema.

How do you validate a JSON file against a schema?

The simplest way to check if JSON is valid is to load the JSON into a JObject or JArray and then use the IsValid(JToken, JsonSchema) method with the JSON Schema. To get validation error messages, use the IsValid(JToken, JsonSchema, IList<String> ) or Validate(JToken, JsonSchema, ValidationEventHandler) overloads.

What is a schema in Python?

schema is a library for validating Python data structures, such as those obtained from config-files, forms, external services or command-line parsing, converted from JSON/YAML (or something else) to Python data-types.


1 Answers

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.

like image 128
Daniel Schneider Avatar answered Sep 28 '22 03:09

Daniel Schneider