Schema guide¶
django-jsonform currently implements a custom JSON Schema spec written specifically for Django.
You should also read the standard spec at https://json-schema.org.
At present, certain features from the standard spec are not supported by django-jsonform. However, we’ve also implemented a few extra features which are not in the standard spec.
For some complex schema examples, see Examples page.
Types¶
Currently, only these six types are supported:
array
(alias list
)¶
A JSON array (similar to Python list).
Keywords:
items
(required) - Specifies the type of items allowed in the list.minItems
(aliasmin_items
) - Limit the minimum number of items in a list.maxItems
(aliasmax_items
) - Limit the maximum number of items in a list.title
- Specify a title for the list.default
- A list containing all the default initial values for the array.
Changed in version 2.8: Support for setting initial array data using default
keyword was added.
This example shows a schema of a list containing string items:
# Schema
{
'type': 'list', # or 'array'
'items': {
'type': 'string',
'default': 'Hello', # default value for new items
'readonly': True, # make all items readonly
},
'min_items': 1,
'max_items': 5,
'default': ['One', 'Two', 'Three'], # initial value for the whole list
}
# Output data
['one', 'two', 'three', ...]
object
(alias dict
)¶
A JSON object (similar to Python dict).
Keywords:
properties
(aliaskeys
; required) - Specifies the keys (or fields) in a dict/object.additionalProperties
- Allow users to add extra keys not declared in the schema.title
- Specify a title for the dict.
This example shows a schema of a basic dict:
# Schema
{
'type': 'dict': # or 'object'
'keys': { # or 'properties'
'name': {
'type': 'string'
},
'email': {
'type': 'string'
},
'age': {
'type': 'number',
'title': 'Age in years',
'default': 50, # default value for age
'readonly': True, # make it readonly
}
}
}
# Output data
{
'name': 'John Doe',
'email': 'john@example.com',
'age': 99
}
Additional keys¶
By default, an object’s data can only contain keys declared in the schema.
But you can allow users to add extra keys using the additionalProperties
keyword.
The additionalProperties
keyword can be:
a schema. You can provide a sub-schema for the new properties.
a boolean. As a shortcut for adding string keys only, you can set this to
True
.a reference. You can also use the
$ref
keyword to reference and reuse existing schema. See Referencing schema docs below to learn more.
Changed in version 2.10: Support for sub-schema for new properties was added.
# Schema
{
'type': 'dict': # or 'object'
'keys': { # or 'properties'
'name': { 'type': 'string' },
},
'addtionalProperties': True
# or
'additionalProperties': { 'type': 'string' }
}
# Output data
{
'name': 'John Doe', # declared in the schema
'gender': 'Male', # added by the user
}
string
¶
A string.
This can’t be at the top level of the schema. If you only want to save
a string, you should use Django’s CharField
.
Keywords:
title
- Specify the label for the input field.choices
(aliasenum
) - Specify choices for the field. Aselect
input will be rendered. See the document on Choices for details.format
- Use this to specify the input field type. See Inputs for string type for more.widget
- Use this to specify the input field type, such as a textarea. For most use cases, prefer theformat
keyword.default
- Specify a default value for this input field.readonly
(aliasreadOnly
) - Make this input field readonlyhelp_text
(aliashelpText
) - Display a help text under this inputplaceholder
- Placeholder text for this inputhandler
- URL of file upload view. See Uploading files for usage.
Changed in version 2.6: Support for default
and readonly
keywords was added.
Changed in version 2.9: Support for help_text
(or helpText
) keywords was added.
Changed in version 2.11: Support for placeholder
, enum
and handler
keywords was added.
number
¶
A number (including floats).
This can’t be at the top level of the schema. If you only want to save a number,
you should use Django’s FloatField
.
Keywords:
title
- Specify the label for the input field.choices
(aliasenum
) - Specify choices for the field. Aselect
input will be rendered. See the document on Choices for details.default
- Specify a default value for this input field. The value must be of numerical type.readonly
(aliasreadOnly
) - Make this input field readonlyhelp_text
(aliashelpText
) - Display a help text under this inputplaceholder
- Placeholder text for this input
It gets a number
HTML input by default. It can’t be overridden.
Changed in version 2.6: Support for default
and readonly
keywords was added.
Changed in version 2.9: Support for help_text
(or helpText
) keywords was added.
Changed in version 2.11: Support for placeholder
and enum
keywords was added.
integer
¶
An integer.
This can’t be at the top level of the schema. If you only want to save an
integer, you should use Django’s IntegerField
.
Keywords:
title
- Specify the label for the input field.choices
(aliasenum
) - Specify choices for the field. Aselect
input will be rendered. See the document on Choices for details.default
- Specify a default value for this input field. The value must be an integer.help_text
(aliashelpText
) - Display a help text under this inputreadonly
(aliasreadOnly
) - Make this input field readonlyplaceholder
- Placeholder text for this input
It gets a number
HTML input by default. It can’t be overridden.
Changed in version 2.6: Support for default
and readonly
keywords was added.
Changed in version 2.9: Support for help_text
(or helpText
) keywords was added.
Changed in version 2.11: Support for placeholder
and enum
keywords was added.
boolean
¶
A boolean.
This can’t be at the top level of the schema. If you only want to save an boolean,
you should use Django’s BooleanField
.
Keywords:
title
- Specify the label for the input field.default
- Specify a default value for this input field. Must be a boolean.readonly
(aliasreadOnly
) - Make this input field readonlyhelp_text
(aliashelpText
) - Display a help text under this input
It gets a checkbox
HTML input by default. It can’t be overridden.
Changed in version 2.6: Support for default
and readonly
keywords was added.
Changed in version 2.9: Support for help_text
(or helpText
) keywords was added.
Referencing schema¶
New in version 2.10.
JSON schema specification allows you to reference parts of schema for reuse in multiple places. This feature also allows you to recursively nest an object within itself.
$ref
keyword¶
Use the $ref
keyword to reference other parts of the schema.
In the following example, shipping_address
has same fields as
billing_address
. So, instead of defining the schema twice, you can reference
the earlier defined schema.
{
'type': 'object',
'properties': {
'billing_address': {
'type': 'object',
'properties': {
'street': { 'type': 'string' },
'city': { 'type': 'string' },
'state': { 'type': 'string' }
}
},
'shipping_address': { '$ref': '#/properties/billing_address' }
}
}
$defs
keyword¶
You can define common schema and keep them in a single place under the $defs
object:
{
'type': 'object',
'properties': {
'billing_address': {
'$ref': '#/$defs/address'
},
'shipping_address': {
'$ref': '#/$defs/address'
}
},
'$defs': {
'address': {
'type': 'object',
'properties': {
'street': { 'type': 'string' },
'city': { 'type': 'string' },
'state': { 'type': 'string' }
}
}
}
}
See also
- Structuring a complex schema
Official documentation on referencing and nesting on JSON Schema’s website
Recursive nesting¶
The $ref
keyword also makes recursion possible. You can use it for
recursively nesting an object within itself.
For example, a Menu object can have link items and a sub-menu (dropdown menu) which contains more links and a sub-sub-menu and so on…
{
'type': 'array',
'title': 'Menu',
'items': {
'type': 'object',
'properties': {
'text': {
'type': 'string',
'title': 'Display text for the item'
},
'link': {
'type': 'string',
'title': 'URL of the item'
},
'children': { '$ref': '#' }
}
}
}
Caution
Beware of the infinite loop while referencing.
In certain cases, referencing ($ref
) may cause an infinite loop.
Currently, that error is unhandled, and the widget will not be rendered at
all if that happens.
One particular case is when two objects reference each other. For example,
a
is a reference to b
and b
is a reference to a
.
There might be other cases, too. If the widget doesn’t render while you’re
using $ref
, please open your browser’s dev console to check the error
message.
Also, open an issue on Github.
Infinite loop error handling will be improved in a future release.
Unsupported features¶
These features are not supported by django-jsonform yet. These are planned to be added in future but there’s no definite ETA:
Validation
anyOf
/allOf
/oneOf