13

Working from this example I want to break the schema into smaller separate schema files. Is this possible and if so how do I reference a relative path to the schema files?

The baseSchema looks like this

{
    "id": "http://some.site.somewhere/entry-schema#",
    "$schema": "http://json-schema.org/draft-04/schema#",
    "description": "schema for an fstab entry",
    "type": "object",
    "required": [ "storage" ],
    "properties": {
        "storage": {
            "type": "object",
            "oneOf": [
                { "$ref": "#/definitions/diskDevice" },
                { "$ref": "#/definitions/diskUUID" },
                { "$ref": "#/definitions/nfs" },
                { "$ref": "#/definitions/tmpfs" }
            ]
        },
        "fstype": {
            "enum": [ "ext3", "ext4", "btrfs" ]
        },
        "options": {
            "type": "array",
            "minItems": 1,
            "items": { "type": "string" },
            "uniqueItems": true
        },
        "readonly": { "type": "boolean" }
    },
    "definitions": {
        "diskDevice": {},
        "diskUUID": {},
        "nfs": {},
        "tmpfs": {}
    }
}

definitions would be these

diskDevice

{
    "properties": {
        "type": { "enum": [ "disk" ] },
        "device": {
            "type": "string",
            "pattern": "^/dev/[^/]+(/[^/]+)*$"
        }
    },
    "required": [ "type", "device" ],
    "additionalProperties": false
}

diskUUID

{
    "properties": {
        "type": { "enum": [ "disk" ] },
        "label": {
            "type": "string",
            "pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
        }
    },
    "required": [ "type", "label" ],
    "additionalProperties": false
}

nfs

{
    "properties": {
        "type": { "enum": [ "nfs" ] },
        "remotePath": {
            "type": "string",
            "pattern": "^(/[^/]+)+$"
        },
        "server": {
            "type": "string",
            "oneOf": [
                { "format": "host-name" },
                { "format": "ipv4" },
                { "format": "ipv6" }
            ]
        }
    },
    "required": [ "type", "server", "remotePath" ],
    "additionalProperties": false
}

tmpfs

{
    "properties": {
        "type": { "enum": [ "tmpfs" ] },
        "sizeInMB": {
            "type": "integer",
            "minimum": 16,
            "maximum": 512
        }
    },
    "required": [ "type", "sizeInMB" ],
    "additionalProperties": false
}

so my directory structure looks like this

enter image description here

so Instead of placing diskDevice, diskUUID, nfs, tempfs in the 'definitions' of the root schema, I want to place them each in their own files as separate schemas.

erotavlas
  • 4,274
  • 4
  • 45
  • 104

1 Answers1

9

To break them up into separate files, you need to change the references and supply each definition with an id. To use diskDevice.json as an example:

baseSchema.json

{
    "id": "http://some.site.somewhere/baseSchema.json#",
    ...
    "properties": {
        "storage": {
            "type": "object",
            "oneOf": [
                { "$ref": "diskDevice.json#" },
                { "$ref": "diskUUID.json#" },
                { "$ref": "nfs.json#" },
                { "$ref": "tmpfs.json#" }
            ]
        },
        ...
    }
}

I would change the id to match the file name, as it makes the relationships between ids and files a little clearer.

You also need to change the refs from JSON pointers within the schema to the ids of the schemas you want to reference. Note that the ids resolve like relative URLs. That is diskDevice.json# resolves to http://some.site.somewhere/diskDevice.json#.

diskDevice.json

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "id": "http://some.site.somewhere/diskDevice.json#",
    "type": "object",
    ...
}

You need to give the separated schemas ids. Again, I would use ids that match the file names - to make things clear. (You should also add $schema and type.)

Using the schemas

What you do with these schemas will depend upon your validator. With the validator that I use (ajv) I load all of the schemas and it resolves them using their ids.

cartant
  • 57,105
  • 17
  • 163
  • 197
  • Does the base URL http://some.site.somewhere/baseSchema.json# represent the path to the base schema file? I'm not storing the schema definitions online, they will be stored on local disk. – erotavlas Aug 16 '16 at 14:03
  • No. Not necessarily. It's just a namespacing mechanism - or can be used as one, at least. Mine are stored as files and are loaded into ajv manually, so to speak. ajv then resolves them via I'd once they are all loaded. Different validators will likely behave in different ways, but you certainly should not need to serve the schema's. – cartant Aug 16 '16 at 14:15
  • So how does it know where to look for the file? What if one of the schema files resides in a subfolder for example? How would that look? – erotavlas Aug 16 '16 at 14:21
  • You might want to post that as a separate, validator-specific question. This answer details how schema ids and refs work to resolve separate schemas. How you load them into a validator will very much depend upon the validator in question. With ajv, I load the files, it does not find them. – cartant Aug 16 '16 at 14:31