Slots

Schema composition

The slots are a new way to create customizable JSON schemas. Slots are replaceable parts of a schema, and they are very similar to named slots in HTML. A slot must contain a valid JSON schema.

$slots keyword

This keyword is used to evaluate current slots, or their fallback if the slots are not provided using the $inject keyword. The value of this keyword must be an object, the property names represents slot names, and the values contain fallback schema.

{
 "$slots": {
  "optional": true,
  "required": false,
  "alias": "slot-name",
  "email": {
   "type": "string",
   "format": "email"
  },
  "some-ref": {
   "$ref": "other-schema.json"
  }
 }
}

In the above schema we have five slots, named: optional, required, alias, email, and some-ref. Schemas provided by injected slots named like so are evaluated. If, for example, the slot email is not injected, the schema that will be evaluated is

{
 "type": "string",
 "format": "email"
}

If the slot other-slot-name is injected, his schema is not evaluated because that name is not present in $slots object.

Other things to note:

  • if the fallback value of a slot is true - the slot is optional (because boolean schema true validates any data)
  • if the fallback value of a slot is false - the slot is required (because boolean schema false validates nothing)
  • if the fallback value of a slot is a string - the slot is resolved with the name extracted from value (alias)

$inject keyword

This keyword injects new slots into the current execution context, and can only be used next to $ref keyword. The value of this keyword must be an object, the property names represents slot names, and the values must be valid JSON schemas.

{
 "$ref": "other-schema.json",
 "$inject": {
  "mail": {"type": "string", "format": "email"},
  "name": true
 }
}

Examples

In this example we are trying to create a customizable user schema. Our user is very simple, contains only two properties: name and age. The name should be a string, and the age should be an integer >= 18. Something like this:

{
  "$id": "http://example.com/user.json",

  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "age": {
      "type": "integer",
      "minimum": 18
    }
  },
 
  "required": ["name", "age"]
}

Now we want to allow extra validations for properties. So wa add some slots

{
  "$id": "http://example.com/user.json",

  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "$slots": {
        "name-prop": true
      }
    },
    "age": {
      "type": "integer",
      "$slots": {
        "age-prop": {
         "minimum": 18
        }
      }
    }
  },

  "required": ["name", "age"]
}

The name property contains one slot named name-prop, the fallback is true which means that the slot is optional. The age property contains one slot named age-prop, the fallback is a schema that checks if the value is at least 18 - this way we can override the minimum value.

If there are no slots injected, the name can be any string, and the age must be an integer >= 18.

Now, let’s inject some slots.

{
 "$ref": "http://example.com/user.json",

 "$inject": {
  "name-prop": {
   "minLength": 3,
   "maxLength": 20
  },
  "age-prop": {
   "minimum": 21,
   "maximum": 65
  }
 }
}
Input Status
{"name": "opis", "age": 50} valid
{"name": "op", "age": 50} invalid - min length for name is 3
{"name": "opis", "age": 18} invalid - min age is 21