Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I break a json schema into separate files?

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.

like image 701
erotavlas Avatar asked Aug 12 '16 20:08

erotavlas


1 Answers

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.

like image 166
cartant Avatar answered Oct 25 '22 11:10

cartant