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.
For data validation, see Validation page.
Types¶
Currently, only these seven types are supported:
array
(alias list
)¶
A JSON array (similar to Python list).
Keywords:
Keyword |
Description |
---|---|
|
Specifies the scheme for the items allowed in the list. |
|
Specify a title for the list. |
|
A list containing all the default initial values for the array. |
Validation keywords:
Keyword |
Description |
---|---|
|
Limit the minimum number of items in a list. |
|
Limit the maximum number of items in a list. |
|
Whether all items in the list must be unique or not. |
Changed in version 2.8: Support for setting initial array data using default
keyword was added.
Changed in version 2.12: Support for uniqueItems
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
},
'minItems': 1,
'maxItems': 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:
Keyword |
Description |
---|---|
|
Specifies the keys (or fields) in a dict/object. |
|
Allow users to add extra keys not declared in the schema. |
|
Specify a title for the dict. |
|
A list containing names of required object properties (keys). |
Changed in version 2.16.0: Support for required
keyword for object properties was added.
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
}
},
'required': ['email']
}
# 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:
Keyword |
Description |
---|---|
|
Specify the label for the input field. |
|
Specify choices for the field.
See the document on Choices for more.
|
|
Use this to specify the input field type.
See Inputs for string type for more.
|
|
Use this to specify the input field type, such as a textarea.
For most use cases, prefer the
format keyword. |
|
Specify a default value for this input field. |
|
Make this input field readonly. |
|
Display a help text under this input. |
|
Placeholder text for this input. |
Validation keywords:
Keyword |
Description |
---|---|
|
Whether this field is required or not. |
|
Minimum required length. |
|
Maximum allowed length. |
Changed in version 2.6: Support for default
and readonly
keywords was added.
Changed in version 2.9: Support for helpText
(or help_text
) keywords was added.
Changed in version 2.11: Support for placeholder
, enum
and handler
keywords was added.
Changed in version 2.12: Support for required
, minLength
and maxLength
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
.
It gets a number
HTML input by default. It can be overridden using the range
widget.
Keywords:
Keyword |
Description |
---|---|
|
Specify the label for the input field. |
|
Specify choices for the field.
See the document on Choices for more.
|
|
Use this to specify the input field type, such as a range input. |
|
Specify a default numerical value for this input field. |
|
Make this input field readonly. |
|
Display a help text under this input. |
|
Placeholder text for this input. |
Validation keywords:
Keyword |
Description |
---|---|
|
Whether this field is required or not. |
|
Minimum allowed value including this limit. |
|
Maximum allowed value including this limit. |
|
Minimum allowed value excluding this limit. |
|
Maximum allowed value excluding this limit. |
Changed in version 2.6: Support for default
and readonly
keywords was added.
Changed in version 2.9: Support for helpText
(or help_text
) keywords was added.
Changed in version 2.11: Support for placeholder
and enum
keywords was added.
Changed in version 2.12: Support for required
, minimum
and maximum
, exclusiveMinimum
and exclusiveMaximum
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
.
It gets a number
HTML input by default. It can be overridden using the range
widget.
Keywords:
Keyword |
Description |
---|---|
|
Specify the label for the input field. |
|
Specify choices for the field.
See the document on Choices for more.
|
|
Use this to specify the input field type, such as a range input. |
|
Specify a default numerical value for this input field. |
|
Make this input field readonly. |
|
Display a help text under this input. |
|
Placeholder text for this input |
Validation keywords:
Keyword |
Description |
---|---|
|
Whether this field is required or not. |
|
Minimum allowed value including this limit. |
|
Maximum allowed value including this limit. |
|
Minimum allowed value excluding this limit. |
|
Maximum allowed value excluding this limit. |
Changed in version 2.6: Support for default
and readonly
keywords was added.
Changed in version 2.9: Support for helpText
(or help_text
) keywords was added.
Changed in version 2.11: Support for placeholder
and enum
keywords was added.
Changed in version 2.12: Support for required
, minimum
and maximum
, exclusiveMinimum
and exclusiveMaximum
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
.
It gets a checkbox
HTML input by default. It can’t be overridden.
Keywords:
Keyword |
Description |
---|---|
|
Specify the label for the input field. |
|
Specify choices for the field.
See the document on Choices for more.
|
|
Use this to specify the input field type, such as a radio input. |
|
Specify a default boolean value for this input field. |
|
Make this input field readonly. |
|
Display a help text under this input. |
Validation keywords:
Keyword |
Description |
---|---|
|
Whether this field is required or not. |
Changed in version 2.6: Support for default
and readonly
keywords was added.
Changed in version 2.9: Support for helpText
(or help_text
) keywords was added.
Changed in version 2.12: Support for required
keyword was added.
const
¶
New in version 2.20.
A constant value.
It gets a readonly input by default. It can also be hidden using the hidden
widget.
Usage:
# Schema
{
'type': 'object',
'title': 'Human',
'properties': {
'species': { 'const': 'Homo sapiens' },
'name': { 'type': 'string' },
},
}
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.
oneOf
, anyOf
and allOf
¶
New in version 2.16.0.
The widget provides support for oneOf
, anyOf
and allOf
, however, with
certain limitations.
oneOf
¶
New in version 2.16.0.
Limitations:
As per the JSON schema specification,
oneOf
means exactly one subschema should match the data. If multiple matches are found, then that should be treated as invalid. But the built-in validation doesn’t make that check. It only checks for at least one match (not exactly one match). If this is something you care about, you are advised to write custom validation.Can’t be used with
additionalProperties
.
{
'type': 'object',
'oneOf': [
{
'properties': {
'age': {'type': 'number'}
}
},
{
'properties': {
'date_of_birth': {'type': 'string', 'format': 'date-time'}
}
}
]
}
anyOf
¶
New in version 2.16.0.
Limitations:
Can’t be used with
additionalProperties
.
{
'type': 'array',
'items': {
'anyOf': [
{'type': 'number'},
{'type': 'string'}
]
}
}
allOf
¶
New in version 2.16.0.
Limitations:
Can only be used inside
object
type. Will not work inside arrays or other types as it may lead to conflicting subschemas.
{
'type': 'object',
'allOf': [
{
'properties': {
'age': {'type': 'number'}
}
},
{
'properties': {
'date_of_birth': {'type': 'string', 'format': 'date-time'}
}
}
],
'additionalProperties': True # additionalProperties can be used with allOf
}