JSON Schema shorthand definition specification.
Expand Javascript shorthand:
{ title: 'string', text: 'string' }
into JSON Schema:
{
"$schema": "http://json-schema.org/schema#",
"type": "object",
"properties": {
"title": {
"type": "string"
},
"text": {
"type": "string"
}
}
}
{
"$schema": "http://json-schema.org/schema#",
"type": "object",
"properties": {
"modifier": {
"type": "string"
},
"text": {
"type": "string"
}
}
}
{ modifier: 'string', text: 'string' }
-
A top-level object is assumed to define a component object schema, and so is assigned a
$schema
value. -
Each
'property': value
pair is assumed to represent an item on"properties"
. -
if
value
is astring
,'property': 'value'
is mapped to"property": { "type": "value" }
, -
if
value
is anobject
,'property': value
is mapped to"property": value
.If the'type'
property is absent fromvalue
,"string"
is inferred.
{
"$schema": "http://json-schema.org/schema#",
"type": "object",
"properties": {
"disabled": {
"type": "boolean"
},
"modifiers": {
"type": "string",
"enum": ["large", "small", "primary"]
},
"iconName": {
"type": "string"
},
"iconClasses": {
"type": "string"
},
"text": {
"type": "string"
},
"href": {
"type": "string"
}
},
"required": ["text"],
"dependencies": {
"iconClasses": ["iconName"]
}
}
{
disabled: 'boolean',
modifiers: ['large', 'small', 'primary'],
iconName: 'string',
iconClasses: {
$dependencies: 'iconName',
$type: 'string'
},
text: {
$required: true,
$type: 'string'
},
href: 'string'
}
- An array
value
is assumed to be an enum. If all items in the array are the same type, them enum will be declared to be of that type; otherwise no type will be declared. - Certain properties that match top-level JSON Schema object properties, such as
dependencies
, are hoisted.
{
"$schema": "http://json-schema.org/schema#",
"type": "object",
"properties": {
"listItems": {
"type": "array",
"items": {
"type": "string"
}
},
"otherList": {
"type": "array"
},
"finalList": {
"type": "array"
}
}
}
JS Shorthand:
{
listItems: 'string[]',
otherList: '[]',
finalList: 'array'
}
Given a 'property': value
pair:
- If
value
equals'array'|'[]'
, then'property': 'value'
is mapped to"property": { "type": "array" }
. - If
value
matches'{type}[]'
, then'property': 'value'
is mapped to"property": { "type": "array", "items": { "type": "{type}" } }
.
{
"$schema": "http://json-schema.org/schema#",
"type": "object",
"properties": {
"modifiers": {
"type": "string"
},
"img": {
"type": "object",
"properties": {
"modifiers": {
"type": "string",
"enum": ["primary", "secondary"]
},
"src": {
"type": "string"
},
"alt": {
"type": "string"
}
}
},
"pill": {
"$ref": "@pill"
},
"title": {
"type": "string"
},
},
"required": ["title"]
}
{
modifiers: 'string',
pill: '@pill',
img: {
modifiers: ['primary', 'secondary'],
src: 'string',
alt: 'string'
},
title: {
$required: true,
$type: 'string'
}
}
- To refer to other components, a component name with an '@' identifier will be expanded to a $ref.
Given a Text Input that references another component, which in turns references another component, all of which share a flat data structure, how do we compose the schema?
-
@text-input
: -
@form-unit
: -
@label
:
-
@text-input
:{ "$schema": "http://json-schema.org/schema#", "id": "@text-input", "type": "object", "allOf": [{ "$ref": "@label" }, { "$ref": "@form-unit" }, { "properties": { "placeholder": { "type": "string" }, "inputClass": { "type": "string", "enum": ["inline", "constrained"] }, "inputId": { "type": "string" }, } } ], "required": ["inputId"] }
-
@form-unit
:{ "$schema": "http://json-schema.org/schema#", "id": "@form-unit", "type": "object", "properties": { "formUnitClass": { "type": "string", "enum": ["inline", "constrained"] }, "label": { "type": "string" }, "@partial-block": { "type": "string" } } }
-
@label
:{ "$schema": "http://json-schema.org/schema#", "id": "@label", "type": "object", "properties": { "labelClass": { "type": "string", "enum": ["inline", "block"] }, "inputId": { "type": "string" }, "labelId": { "type": "string" }, "@partial-block": { "type": "string" }, "requiredText": { "type": "string" }, }, "required": ["inputId"] }
{
$include: ['@label', '@form-unit'],
placeholder: 'string',
inputClass: ['inline', 'constrained'],
inputId: {
$type: 'string',
$required: true
}
}
$include
expands the listed ids into an allOf
expression, and also includes any additional properties listed.
- Should a convention be able to define a non-component ref, similar to https://metacpan.org/pod/JSON::Schema::Shorthand? i.e.
{
pill: '#/units/pill'
}
- Should undefined 'types' be inferred, and if so, what should the value be?