JSON Schema

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.

Two Ways to declare Names

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

Primitives

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 number type.

“boolean”

Value must be a boolean, either true or false.

Array Specifics

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" ]
}

Schema Restrictions

Type Declaration

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:

../../../../_images/json-schema.png

Limitations

In a type declaration, the following limitations must be observed.

  1. 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
        }
    }
    
  2. 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
        }
    }
    
  3. 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"
                 }
             }
         }
    }
     }
    

Version String Comparison

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