Skip to main content

Schema Reference

The schema is a JSON Schema document that describes the shape of the data your form collects. JSON Forms uses the schema both to pick an appropriate renderer for each property and to validate what customers enter.

This page is a practical tour of JSON Schema as applied to JSON Forms in Prismatic. It covers the types, keywords, and patterns you'll reach for most often, along with notes on how each one influences the generated form. The JSON Schema specification is authoritative for any keyword that isn't called out here.

Top-level shape

A JSON Forms schema is almost always an object with a properties map:

Schema shape
{
"type": "object",
"properties": {
"companyName": { "type": "string" },
"numEmployees": { "type": "integer" }
},
"required": ["companyName"]
}

The top-level type can also be "array" when the entire form collects a list of items.

Supported types

typeDefault rendererNotes
stringText inputSee formats for date, time, password, and so on
integerNumber inputWhole numbers only
numberNumber inputDecimal numbers
booleanCheckboxSet options.toggle on the UI schema element to render as a switch
objectNested groupTypically used to compose form sections
arrayTable layoutArray of objects; Prismatic defaults to a table layout

See the renderers reference for a complete type-to-renderer mapping.

Nested objects

Objects nest inside other objects with their own properties and required arrays. The generated form data preserves the shape exactly - if the schema has a company object with name and headcount properties, the form data will have a company object with name and headcount properties:

Nested object
{
"type": "object",
"properties": {
"company": {
"type": "object",
"properties": {
"name": { "type": "string" },
"headcount": { "type": "integer" }
},
"required": ["name"]
}
}
}

Nested objects render inline inside their parent layout by default. Wrap them in a Group in the UI schema to add a visible label and container. For shapes reused in more than one place, see References with $ref.

Formats

Set format on a string property to pick a specialized renderer, a validator, or both.

Prismatic supports these formats:

date

Renderer: Date picker

Accepted values: ISO 8601 date strings in YYYY-MM-DD form, such as 2026-04-21.

Use with formatMinimum and formatMaximum to constrain the selectable range.

time

Renderer: Time picker

Accepted values: ISO 8601 time strings in HH:mm:ss form, such as 14:30:00. Fractional seconds (HH:mm:ss.sss) and an optional timezone suffix (Z or ±HH:mm) are also accepted.

date-time

Renderer: Date-and-time picker

Accepted values: Full ISO 8601 timestamps combining a date and time with a T separator and a timezone suffix, such as 2026-04-21T14:30:00Z.

password

Renderer: Masked text input

Accepted values: Any string. This format affects presentation only - it does not validate content.

email

Renderer: Text input

Accepted values: A standard email address in local-part@domain form, such as alex@example.com.

uri

Renderer: Text input

Accepted values: An absolute URI that includes a scheme, such as https://example.com/widgets/42. Relative URIs are rejected.

ipv4

Renderer: Text input

Accepted values: Four dot-separated integers from 0 to 255, such as 192.0.2.1.

Example

Date and password formats
{
"type": "object",
"properties": {
"startDate": { "type": "string", "format": "date" },
"apiKey": { "type": "string", "format": "password" }
}
}

Validation keywords

Prismatic validates user input against the standard JSON Schema validation keywords. The following are the ones you'll use most often:

KeywordApplies toDescription
requiredobjectArray of property names that must be present
minLength / maxLengthstringMinimum and maximum string length
patternstringRegular expression the input must match
minimum / maximuminteger, numberNumeric bounds
exclusiveMinimum / exclusiveMaximuminteger, numberExclusive numeric bounds
multipleOfinteger, numberValue must be a multiple of this number
formatMinimum / formatMaximumstring with formatInclusive bounds for date, time, and date-time formats
formatExclusiveMinimum / formatExclusiveMaximumstring with formatExclusive bounds for date, time, and date-time formats
minItems / maxItemsarrayBounds on the number of items
uniqueItemsarrayWhen true, all items must be unique

Validation runs continuously as the customer types. You can change when errors display with the Validation Mode setting on the config variable - see Validation mode.

For validation that the schema alone can't express, see JSON Form Validation.

Default values and pre-filling the form

To pre-fill a form with initial values, return a data property alongside schema and uiSchema from your data source:

Data source return value with pre-filled data
{
"schema": {
/* ... */
},
"uiSchema": {
/* ... */
},
"data": {
"region": "us-east-1",
"retryCount": 3,
"enableCache": true
}
}

See Pre-filling forms with default data for the full pattern.

The schema's default keyword is an annotation - it describes what a property's default value would be, but doesn't pre-populate the form. Return data from your data source whenever you want the form to open with values already filled in.

Fixed values with const

const asserts that a property holds a specific value. Its primary use in JSON Forms is inside a oneOf array to build dropdowns where the displayed label and the stored value differ:

const inside oneOf
{
"continent": {
"type": "string",
"oneOf": [
{ "title": "North America", "const": "NA" },
{ "title": "Europe", "const": "EU" }
]
}
}

See Dropdowns with enum and oneOf for the full pattern.

Two schema patterns produce dropdown menus:

  • enum - a flat array of string values. The customer sees the same value that the config variable stores.
  • oneOf - an array of { "title": ..., "const": ... } objects. The customer sees the title; the config variable stores the const.
enum
{
"continent": {
"type": "string",
"enum": ["North America", "Europe", "Asia"]
}
}
oneOf with custom values
{
"continent": {
"type": "string",
"oneOf": [
{ "title": "North America", "const": "NA" },
{ "title": "Europe", "const": "EU" },
{ "title": "Asia", "const": "AS" }
]
}
}

Use oneOf whenever the display label and stored value need to differ, or when you're populating the list from a third-party API and want to store a stable ID.

Add options.autocomplete: true to the UI schema element to render a oneOf dropdown as a type-ahead.

Arrays

Arrays let the customer add one or more items with the same structure:

Array of objects
{
"type": "array",
"items": {
"type": "object",
"properties": {
"channel": { "type": "string" },
"notification": { "type": "string", "enum": ["Created", "Updated"] }
},
"required": ["channel", "notification"]
}
}

By default, arrays render as a table. Use options.layout to switch to an accordion instead, or use the ListWithDetail UI type for a master-detail layout.

minItems, maxItems, and uniqueItems apply to the array itself. Validation keywords on items apply to each array entry.

References with $ref

Prismatic resolves every $ref in your schema before rendering the form. This lets you reuse subschemas without worrying about whether a specific renderer resolves references on its own.

Schema with a shared subschema
{
"type": "object",
"definitions": {
"address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" }
},
"required": ["street", "city"]
}
},
"properties": {
"billing": { "$ref": "#/definitions/address" },
"shipping": { "$ref": "#/definitions/address" }
}
}

Descriptions and titles

Both description and title on a property surface in the UI:

  • description appears as helper text beneath the input.
  • title overrides the auto-generated label (otherwise derived from the property name).

The UI schema's label takes precedence over the schema's title when both are set. Descriptions show even when the input is not focused unless you set options.showUnfocusedDescription: false.

Required fields

Mark required fields in the parent object's required array, not on the field itself:

required
{
"type": "object",
"properties": {
"companyName": { "type": "string" },
"companyDescription": { "type": "string" }
},
"required": ["companyName"]
}

Required fields display an asterisk next to their label. Set options.hideRequiredAsterisk: true on a control or layout to suppress the asterisk for that element.

Composing schemas with allOf, anyOf, oneOf, and not

The composition keywords let you validate against multiple subschemas and pull properties from them into the form. JSON Forms walks into these subschemas when a UI schema control scopes a property defined inside one of them, so a property declared inside an allOf branch renders just like a top-level property would:

Property defined inside allOf
{
"type": "object",
"allOf": [
{
"properties": {
"accountId": { "type": "string" }
}
}
],
"properties": {
"accountName": { "type": "string" }
}
}
UI schema referencing the allOf-defined property
{
"type": "VerticalLayout",
"elements": [
{ "type": "Control", "scope": "#/properties/accountName" },
{ "type": "Control", "scope": "#/properties/accountId" }
]
}

Both controls render, and customer input for accountId flows into the form data as expected.

KeywordValidationRenders properties from the subschema?
allOfYesYes - scope controls to #/properties/<name> and the property resolves.
anyOfYesYes - same resolution as allOf.
oneOfYesYes for full subschemas and in the dropdown pattern ({ "title", "const" } entries on a string property).
notYesNot applicable - not forbids a shape and doesn't contribute properties. Most useful inside UI rule conditions.

Keep in mind: JSON Forms renders every control the UI schema declares regardless of whether the condition's data matches. Composition keywords influence validation, not visibility. For show/hide behavior, use UI rules.

For example, not inside a rule condition expresses "show this element when the country is anything other than the US":

not in a UI rule
{
"rule": {
"effect": "SHOW",
"condition": {
"scope": "#/properties/country",
"schema": {
"not": { "const": "United States" }
}
}
}
}

Conditional validation with if / then / else

if / then / else lets you apply different validation rules depending on the form data:

Conditional validation
{
"type": "object",
"properties": {
"tier": { "type": "string", "enum": ["free", "paid"] },
"promoCode": { "type": "string" }
},
"if": { "properties": { "tier": { "const": "paid" } } },
"then": { "required": ["promoCode"] }
}

Properties declared inside then or else subschemas resolve the same way allOf properties do - scope a control to #/properties/<name> and it renders. What if / then / else doesn't do is hide controls based on the condition; every control the UI schema declares stays visible. For conditional visibility, use UI rules instead.

Keywords Prismatic handles differently

A few JSON Schema keywords are worth calling out because their effect on the form isn't obvious:

  • additionalProperties - Prismatic only renders controls for properties you declare in properties (or reach through composition keywords), so schema-level additionalProperties: false doesn't change the UI. AJV still enforces it during validation when the form data contains keys the schema doesn't cover.
  • readOnly - schema-level readOnly: true disables the input control, so the customer can see the value but not edit it. You can also set options.readonly on a UI schema element to apply the same effect, including to layouts so an entire group becomes non-editable.
  • writeOnly - Prismatic doesn't use writeOnly as a rendering hint. If you need a masked input, use "format": "password" instead.