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

items (required)

Specifies the scheme for the items allowed in the list.

title

Specify a title for the list.

default

A list containing all the default initial values for the array.

Validation keywords:

Keyword

Description

minItems (alias min_items)

Limit the minimum number of items in a list.

maxItems (alias max_items)

Limit the maximum number of items in a list.

uniqueItems

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

properties (alias keys)

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.

required

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

title

Specify the label for the input field.

choices (alias enum)

Specify choices for the field.
See the document on Choices for more.

format

Use this to specify the input field type.

widget

Use this to specify the input field type, such as a textarea.
For most use cases, prefer the format keyword.

default

Specify a default value for this input field.

readonly (alias readOnly)

Make this input field readonly.

helpText (alias help_text)

Display a help text under this input.

placeholder

Placeholder text for this input.

Validation keywords:

Keyword

Description

required

Whether this field is required or not.

minLength

Minimum required length.

maxLength

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

title

Specify the label for the input field.

choices (alias enum)

Specify choices for the field.
See the document on Choices for more.

widget

Use this to specify the input field type, such as a range input.

default

Specify a default numerical value for this input field.

readonly (alias readOnly)

Make this input field readonly.

helpText (alias help_text)

Display a help text under this input.

placeholder

Placeholder text for this input.

Validation keywords:

Keyword

Description

required

Whether this field is required or not.

minimum

Minimum allowed value including this limit.

maximum

Maximum allowed value including this limit.

exclusiveMinimum

Minimum allowed value excluding this limit.

exclusiveMaximum

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

title

Specify the label for the input field.

choices (alias enum)

Specify choices for the field.
See the document on Choices for more.

widget

Use this to specify the input field type, such as a range input.

default

Specify a default numerical value for this input field.

readonly (alias readOnly)

Make this input field readonly.

helpText (alias help_text)

Display a help text under this input.

placeholder

Placeholder text for this input

Validation keywords:

Keyword

Description

required

Whether this field is required or not.

minimum

Minimum allowed value including this limit.

maximum

Maximum allowed value including this limit.

exclusiveMinimum

Minimum allowed value excluding this limit.

exclusiveMaximum

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

title

Specify the label for the input field.

choices (alias enum)

Specify choices for the field.
See the document on Choices for more.

widget

Use this to specify the input field type, such as a radio input.

default

Specify a default boolean value for this input field.

readonly (alias readOnly)

Make this input field readonly.

helpText (alias help_text)

Display a help text under this input.

Validation keywords:

Keyword

Description

required

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:

  1. 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.

  2. 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:

  1. Can’t be used with additionalProperties.

{
    'type': 'array',
    'items': {
        'anyOf': [
            {'type': 'number'},
            {'type': 'string'}
        ]
    }
}

allOf

New in version 2.16.0.

Limitations:

  1. 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
}