Compared with the JSON schema specification JSON-SCH, the schema used for the APS interfaces type declaration has some extensions and limits that application developers should be aware of.
In this document:
A sample JSON schema definition looks as follows:
{
"name": "Book",
"type": "object",
"properties": {
"title": { "type": "string" },
"author": { "type": "string" },
"pages": { "type": "integer" },
"popular": { "type": "boolean" },
"price": { "type": "number" }
}
}
In this example, the “Book” object is defined with explicit declaration of its name
.
Its type is object
and it has 5 properties.
In APS, the following two schema declarations are equally valid:
Option #1: The special name
element is used:
{
"name": "Book",
...
}
Option #2: Name is declared by its position:
"Book": {
// Element name implies that "name" equals "Book"
...
}
The set of allowed APS primitives contains the standard JSON set and is extended with
the integer
type as presented in the table:
Type |
Meaning |
---|---|
“string” |
Value must be a “string”. |
“number” |
Value must be a number, floating point numbers are allowed. Formal syntax is: number = [ minus ] int [ frac ] [ exp ], for example:
-1234.56e3 123E-4 1234
|
“integer” |
Value must be an integer, no floating point numbers are
allowed. This is a subset of the |
“boolean” |
Value must be a boolean, either true or false. |
The array type requires the definition of the allowed type of items in arrays. For this, the additional items
attribute is used. In the following example, the array items must be strings:
{
"name": "Person",
"type": "object",
"properties": {
"friends": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
This definition corresponds to the following JSON data:
{
"friends": [ "Bill", "John", "Jack" ]
}
In APS, a type of a JSON object can be declared as either a primitive (trivial), another JSON object, or an array, as presented in the following diagram:
In a type declaration, the following limitations must be observed.
Type aliasing is not supported, meaning the following declaration will be considered invalid:
{ "MyBook": { "type": "object", "properties": { "type": "string" } }, "AnotherBook": { "type": "MyBook" // Aliasing to the existing type is NOT possible } }
Type recursion (self-reference) is not supported, meaning the following declaration will be considered invalid:
{ "name": "Book", "type": "object", "properties": { "something": { "type": "Book" } // Impossible to refer to the type recursively } }
Arrays inside arrays are not supported, meaning the following declaration will be considered invalid:
{ "name": "Author", "type": "object", "properties": { "books": { "type": "array", "items": { "type": "array", // Array embedded into another array is NOT supported "items": { "type": "Book" } } } } }
Let us consider a case when the format of a type specifies “version”, as in the following example:
{
"name": "Version",
"type": "string",
"format": "version"
}
It is important to consider special logic that is associated with this format in the Resource Query Language. Two versions are compared in the following algorithm:
bool version_less(int[4] v1, int[4] v2)
{
if (v1[0] != v2[0]) return v1[0] < v2[0];
if (v1[1] != v2[1]) return v1[1] < v2[1];
if (v1[2] != v2[2]) return v1[2] < v2[2];
return v1[3] < v2[3];
}
This means each element of the version is interpreted as an integer and compared with the corresponding element in the compared version. If an element is not present in the string, for example, “1.0”, the remaining elements are treated as 0, that is [1, 0, 0, 0].