2

I have multiple large json-schema files. There are properties which are common for many schema files.

To remove redundancy between the common schema definitions, separated those in separated schema files and using $ref to reference to the individual JSON schema.

My directory structure for all schema files are like

/
|- schemas
   |- components
      |- page_layout.json
   |- page.json

The content of page.json is

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "array",
  "examples": [],
  "items": {
    "type": "object",
    "required": [],
    "additionalProperties": false,
    "properties": {
      "type": {
        "type": "string",
        "enum": [
          "page_layout", "banner_images"
        ]
      },
      "data": {
        "type": "object"
      }
    },
    "allOf": [
      {
        "if": {
          "properties": {
            "type": {
              "const": "page_layout"
            }
          }
        },
        "then": {
          "properties": {
            "data": {
              "$ref": "components/page_layout.json"
            }
          }
        }
      }
    ]
  }
}

and the content of page_layout.json file is

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {},
  "type": "object",
  "required": [],
  "additionalProperties": false,
  "properties": {
    "backgroundColor": {
      "type": "string"
    },
    "templateName": {
      "type": "string",
      "enum": ["linear", "square", "circle"]
    }
  }
}

Combining both the files, the example JSON data to be validated is

[
  {
    "type": "page_layout"
    "data": {
      "backgroundColor": "#ff00ff",
      "templateName": "square"
    }
  },
  {
    "type": "banner_images"
    "data": {
      // Content for banner_images
    }
  }
]

Content of data will change depending on the type value.

I'm using python jsonchema to validate the JSON data and the code for validating is

import json
import jsonschema
import os
from json import JSONDecodeError


class SchemaValidator:
    def __init__(self, category: str):
        self.category = category
        self.data = ''

    def _schema(self):
        schema_file = self.category.replace(' ', '_')
        schema_path = os.path.join(os.path.dirname(__file__), 'json_schema', 'categories', '{}.json'.format(schema_file))

        try:
            with open(schema_path, 'r') as file:
                return json.loads(file.read())
        except FileNotFoundError:
            raise Exception('Schema definition missing')
        except JSONDecodeError:
            raise Exception('Schema definition invalid')

    def validate(self, data):
        self.data = data
        try:
            status = jsonschema.validate(json.loads(data), self._schema())
        except jsonschema.SchemaError as e:
            raise Exception(e)

        return status

But this is giving error for the $ref files as

unknown url type: 'components/page_layout.json'
Anuj TBE
  • 9,198
  • 27
  • 136
  • 285
  • By default, JSON Schema has no awareness of physical files or any notation of a file system. In stead, it uses URI resolution rules to determine the correct schema. Once a schema is loaded, the only notion of relative references it has are based on it's base URI, which you set by using $id. – Relequestual Jan 06 '20 at 16:29
  • Does this answer your question? [How to set up local file references in python-jsonschema document?](https://stackoverflow.com/questions/53968770/how-to-set-up-local-file-references-in-python-jsonschema-document) – Relequestual Jan 06 '20 at 16:29
  • You must create your own reference resolve for each schema you wish to reference. You may do so in a loop if you have many. – Relequestual Jan 06 '20 at 16:29

1 Answers1

3

You must specify the protocol identifier

"$ref" : "file://./components/page_layout.json"

https://github.com/python-jsonschema/jsonschema/issues/313

BigLin
  • 31
  • 2