Toggle menu

Schema

As described in End Point Parameter and Return Schema you can define a schema to validate the parameters passed to, and the response received from, your end point. Parameters are checked against the schema before the end point is called.

The schema designer uses a drag and drop editor, similar to the forms designer, that lets you build up your schema. The editor will only ever construct a valid schema, highlighting any problems in red as they occur. However, it is worth remembering that although a schema might be valid, it is perfectly possible to create something that is so restrictive (or contradictory), you won't ever be able to meet the criteria it demands.

Describing the whole of JSON schema is beyond the scope of this article. You can read the full specification at JSON Schema (opens new window). There's also a really good introduction at Understanding JSON Schema (opens new window).

In this article we'll take a look at some example schemas and common mistakes made when designing them.

You can also find a collection of example end point schemas in iCM. A new installation should include the goss.Examples.Schemas namespace which has over twenty example end points in it.

Basic Types

You can build your schema using six basic types. Note that we have implemented distinct types for integer and number, and that the core JSON Schema specification includes a "null" type which we have not included in the iCM designer.

Strings, Numbers and Integers

String Schema
 

This schema expects a single parameter called articleHeading. It is required and no additional pattern, length or formatting restrictions have been set up. The following request parameters would pass the schema above:

{
    "articleHeading": "News"
}

Numbers and integers work in a similar way to strings, but rather than a minimum and maximum length, you can set minimum and maximum values.

Booleans

Boolean Schema
 

Booleans are probably the simplest of the schema types. You are able to set the key name and whether it is required or not. The following request parameters would pass the schema above:

{
    "myBoolean": true
}

Objects

Object Schema
 

Objects are often built up from the other types, and can include other objects nested inside them. In the example above we've stated that the request parameters should include an object, called myObject, which has two properties, one string and one integer, both of which are required. The following request parameters would pass:

{
    "myObject": {
        "myAge": 35,
        "myName": "Tim"
    }
}

If all you need to do is check that an object is present, you can define an object without adding any other types as properties.

The object type also includes minimum and maximum fields, allowing you to state that a certain number of properties must be present in the object, without defining their names.

Arrays

Array Schema
 

The array type is similar to an object type. It acts as a container which can have the other types added to it (so an array of numbers, an array of objects, an array of strings, an array of arrays).

In the example above our array is required, can contain any number of strings, and will not accept any other types of item in it. This makes the array type different to objects - when only a single item is present, any number of those items can be included in the array. Both of these request parameters would pass the schema above:

{
    "myArray": ["Abc", "Bce", "123", "false"]
}

{
    "myArray": ["Abc", "Bce"]
}

If your array schema contains multiple types, the array should contain those types in the correct order. Note however, the items in the array are not required unless you flag each type as required - adding multiple types to an array only checks the ordering of items if they are present.

The schema below would reject the first set of parameters above, but accept the second. It would also accept an array with a single string in it because neither string type is required.

Array of Two Strings Schema
 

Logical Groups

Logical groups can be used to combine or add further restrictions to the basic types. They can be used to assess the parameters and response, and match against allOf, anyOf or oneOf the schema, or exclude items using not.

allOf

To validate against allOf, the request parameters must meet all of the schemas defined in the group.

Impossible logic groups are, unfortunately, very easy to create. For example, if we are expecting our parameters to include a string and a number:

{
    "myString": "hello",
    "myNumber": 5
}

you might think this would be a valid schema:

An Invalid allOf schema
 

What that schema actually defines is a parameter that is both a string and a number - which is impossible.

To make sure our request includes a string and a number, there's actually no need to use a logical group at all. Just add the two basic types and set them both as required:

Required String and Number Schema
 

allOf is most useful when we want to check that a given type meets multiple conditions. In this example we are expecting a single string, but the string has to meet multiple conditions (two in this case):

allOf Logical Group
 

anyOf

Parameters will pass the anyOf logical group test if at least one of the schemas within it are met.

For example, if we know our parameters will include an integer, and we want to check the value is a multiple of either 2, 5, or both, the following logic could be used:

anyOf Logic
 

So the numbers 2, 4, 5, 6, 8 and 10 would all pass this test.

oneOf

Unlike anyOf, where at least one of the schemas must be met, to pass the oneOf logical group, exactly one of the schemas must be met. If the parameters match more than one, the check will fail.

If we change our previous integer example to oneOf:

oneOf Logic
 

The numbers 2, 4, 5, 6 and 8 would pass, but 10 would fail is it meets both schemas.

not

Not is used to check that certain values are not present in our parameters. For example, if we need to make sure a string does not contain the word "test":

not Logic
 

Logical Groups as Top-Level Properties

Creating a schema that only contains the following will return an error:

Top level logical Group
 

Previewing the JSON schema shows why:

{
    "oneOf": [{
            "type": "object",
            "properties": {
                "ObjectID": {
                    "type": "integer"
                }
            }
        },
        {
            "type": "object",
            "properties": {
                "Type": {
                    "type": "string"
                }
            }
        }
    ],
    "additionalProperties": false,
    "type": "object"
}

Note that we have "type": "object" and "additionalProperties": false but haven't defined any properties that are allowed.

There are two ways around this. You could either set additionalProperties as true in the schema settings (also setting additional properties as false in your objects):

Additional properties false
 

Or you could explicitly define the properties you expect:

One Of with Properties
 

Which when previewed shows the following, which will only accept the properties ObjectID and Type, and will only allow one of them:

{
    "additionalProperties": false,
    "oneOf": [
        {
            "type": "object",
            "properties": {
                "ObjectID": {
                    "type": "integer"
                }
            }
        },
        {
            "type": "object",
            "properties": {
                "Type": {
                    "type": "string"
                }
            }
        }
    ],
    "type": "object",
    "properties": {
        "Type": {
            "type": "string"
        },
        "ObjectID": {
            "type": "integer"
        }
    }
}

Last modified on July 31, 2023

Share this page

Facebook icon Twitter icon email icon

Print

print icon