Payload technical reference
Supported JSON schema features
Note
We don’t use the exact same terminology that the JSON Schema standard uses.
Schema properties
The minimum JSON schema is a schema property. A schema property is defined within brackets:
{
"type": "..."
}
The type
keyword specifies which is the type of the property.
Not every property must have a type, but they usually do.
Data types
Every property contained in CyberApp schemas must have a type. There are seven different data types that you can use:
Primitives
Number
Integer
String
Boolean
Null
Composed
Object
Array
A property with Integer type would then be defined as:
{
"type": "integer"
}
Objects and Arrays are special types, but they can be used here as well:
{
"type": "object"
}
Objects
Properties with Object type represent a JSON object with properties. They also support a set of additional attributes that can help defining these properties:
Properties: An Object whose entries define the properties of the object itself. Every entry represents one object property, where the key is the name of the property and the value must be a valid JSON Schema representing the type of the object property. Note that objects can be naturally nested if an object property is also an object.
Important
One of our custom rules is that an Object property can’t be named “[i]”, as we use this name internally.
{ "type": "object", "properties": { "key1": { "type": "string" }, "key2": { "type": "object", "properties": { "innerKey1": { "type": "boolean" } } } } }
Required: By default, none of the properties defined before is mandatory, which means that an empty object would match against our schema. If we want to require them, then we can add the required keyword with a list of the required property names.
{ "type": "object", "properties": { "key1": { "type": "string" }, "key2": { "type": "null" } }, "required": ["key1"] }Note
We can see that
key1
is required in the object, butkey2
is not.
Additional properties: Unless stated otherwise, our schema supports additional properties (properties whose names are not listed). If we don’t want schemas with additional properties to match with ours, then we can set additional properties to false.
{ "type": "object", "properties": { "key1": { "type": "string" }, "key2": { "type": "null" } }, "additionalProperties": false }If we want to accept additional properties - but only if they have a given type - we can define additional properties as a schema property. For example, we will allow additional properties, but only if they are of type number.
{ "type": "object", "properties": { "key1": { "type": "string" }, "key2": { "type": "null" } }, "additionalProperties": { "type": "number" } }
Arrays
Properties with array type represent a JSON array. As such, an array can define the type of the items it will contain.
{
"type": "array",
"items": "string"
}
JSON Schema allows the items to have any type. For example, we can have objects as the items of an array:
{
"type": "array",
"items": {
"type": "object",
"properties": {
"innerArray": {
"type": "array"
}
}
}
}
Or even another array nested inside our first array:
{
"type": "array",
"items": {
"type": "array"
}
}
While all these schemas are considered valid, you should take into account that, due to some technical limitations, you will only be able to map the array nearest to the root of the schema (so, nested arrays are not eligible for mapping).
Compatible types
To create a mapping between two properties, their types must be compatible.
Note
Compatibility is one-sided: if property A is compatible with property B, property B does not necessarily need to be compatible with property A (even though it could be).
Primitive types are only compatible with the same type.
Note
Integer is an exception.Integer is compatible with Number. This means that Integer can be assigned to Number.Number is not compatible with Integer.- Objects are compatible depending on their properties.If all properties in the right object are compatible with their counterpart in the left object, then they are compatible, unless:
the left object is missing properties that are required in the right object.
the left object has additional properties and they are either not compatible with the right object additional properties or the right object does not accept any additional properties.
- Arrays are compatible, depending on their items types.If their items types are compatible, then the arrays are compatible.
Multi-type
Any ofIf any of the multiple types is compatible with the type on the other side, then they are compatible. All ofIf all of the multiple types are compatible with the type on the other side, then they are compatible. One ofIf one (and exactly one) of the multiple types is compatible with the type on the other side, then they are compatible.
A property declaring a multi-type looks like this:
{ "anyOf": [ { "type": "string" }, { "type": "number" } ] }
This means it is any of String or Number. The rest of the conditions are represented in the same way:
{ "oneOf": [ { "type": "string" }, { "type": "number" }, { "type": "null" } ] }
Note
Only primitive types can be used for multi-types. This is a custom rule to ensure consistency in mappings.
A multi-type property with any of
condition can be also represented in a more compact way:
{ "type": ["string", "number", "null"] }
References
{ "type": "object", "properties": { "keyA": { "$ref": "#/definitions/address" } }, "definitions": { "address": { "type": "string" } } }
This is equivalent to the following schema:
{ "type": "object", "properties": { "keyA": { "type": "string" } } }
The syntax can be deducted from the example. The $ref
keyword (including the dollar sign) is used to reference another part of the schema. The path that follows is a string, starting with #
, which represents the root of the schema, and then followed by as many parts as needed. Each part starts with a forward slash (/) and the name of the property that will be traversed. The path must never end in slash.
For the reference to be valid, the path must point to a valid schema inside the root schema. Usually, a collection of definitions is placed at the root level of the schema, but it can be placed anywhere. While a referenced type might also reference another type transitively, circular references are not allowed. As an illustration, the following schema contains a circular reference:
{ "type": "object", "properties": { "keyA": { "$ref": "#/definitions/typeA" } }, "definitions": { "typeA": { "$ref": "#/definitions/typeB" }, "typeB": { "$ref": "#/definitions/typeA" } } }
Since keyA
type is defined by typeA
, but typeA
is defined by typeB
(which is, in turn, defined by typeA
), we reach a loop that will never end.
UI builder form model as a JSON schema
The form model is considered a JSON schema object. Every element is transformed to a JSON schema property inside the object. The property name is the element ID (or model property), and the type is given by the following list:
Active elements
Active elements are available for both request and response mapping.
Input (when element Type property is Text or Textarea): String
Input (when element Type property is Number): Number
Password: String
NumPicker: Number
Switch: Boolean
Select (when multiple is false): Any of <String, Number>
Select (when multiple is true): Array of <Any of <String, Number>>
Checkbox: Boolean
Button-Group (when type is checkbox): Array of <String>
Button-group (when type is radio): String
Datepicker: String
Timepicker: String
Group (when mode is repeater): Array of <Object<{ [component’s model property]: component type following this list }>>