HCMS entities are defined in a extended JSON schema with additional censhare properties.

Introduction

Entities are defined by an extended JSON schema: A JSON document as defined by JSON schema Draft 7 with additional properties that describe storage and mapping details. By convention, these additional properties always start with cs:.

Basic Requirements

The following rules need to be observed when writing a JSON schema for the Headless CMS:

  • Every schema must be explicitly and unambiguously typed using the validation keyword type with a single type except null and optionally null as a secondary type to allow null values.
  • Conditional (if, then, else) and boolean logic (allOf, anyOf, oneOf, not) validation keywords are not supported.
  • For schemas of a scalar type, the appropriate validation keywords out of enum, const, mulitpleOf, maximum, exclusiveMaximum, minimum, exclusiveMinimum, maxLength, minLength and pattern are supported.
  • For schemas that are of the type object, all properties must be specified using sub schemas either with the properties keyword in general or with the patternProperties keyword for some special mappings. The keywords maxProperties, minProperties, required, additionalProperties, dependencies and propertyNames can be used to apply further constraints to the schema.
  • For schemas that are of the type array, the elements must be specified using the keyword items and a single sub schema. The sub schema must not be of the type array itself. The keyword additionalItems is not supported. The keywords maxItems, minItems, uniqueItems and contains can be used to apply further constraints.
  • Schema references ($ref) can be used instead of the allowed validation keywords and must not result in a recursive schema structure.

Basic Mapping

Entities as censhare Assets

All Headless CMS data is stored as entities; each entity is one record in censhare, known as asset, and identified by id, a 64-bit integer number, sequentially assigned and externally represented as JSON document conforming to JSON schema. Entities can be created, updated, deleted and of course read, listed and searched for.

Internal Representation

Although the Headless CMS hides much of the censhare servers internals to the entity API user and provides simple solution for storing data, there are some aspects that must be considered.

Entities are stored as censhare assets, entity properties are stored as asset features, as other assets or as storage files. Some features are always present in features, therefor they are always present in the underlying assets, even when they are not mapped to any property in schema. Especially noteworthy are:

  • "cs:feature.key": "censhare:asset.id"
    • This is the id used as a identifier of the entity
    • It is recommended to be mapped in every schema
    • It is not possible to write this value as it is assigned automatically
  • "cs:feature.key": "censhare:asset.type"
    • This feature identifies the entity type
    • Schema/entity mapping is defined by this feature
    • Changing of this property is not recommended

Mapping Rules

The following mapping rules apply when no censhare specific mapping keywords (cs:*) are used:

  • The whole entity itself is mapped to an censhare asset of an automatically created asset type.
    • The asset type id is constructed using the namespace from the HCMS configuration and the entity name using the following pattern: [namespace].[entity-name].entity.
    • The asset type name and description are derived from the JSON schema properties title and description respectively.
  • Schemas of a scalar type are mapped to censhare asset features using an automatically created feature.
    • The feature id is constructed using the namespace from the HCMS configuration, the entity name and the property name using the following pattern. [namespace].[entity-name]:[property-name]. For nested properties, all property names from the schema root are concatenated using a dot character.
    • The feature value type is Text (String), Integer (Long), Floating-point number (Double) and Boolean for the respective JSON schema types string, integer, number and boolean.
    • When a set of enumeration values is specified using the keywords enum or const for the schema type string or integer, a feature of the value type Value list (String) with the appropriate values is created.
    • The feature name and description are derived from the JSON schema properties title and description respectively.
    • If the scalar property is either missing or has a null value during import the mapped asset feature is deleted.
    • If there is no mapped asset feature during export, the entire property is either skipped or written using a null value of it is part of the required keyword in the schema.
  • Schemas of the type array change the mapping of their sub schema to a multi value censhare feature.
    • The order of the array elements is mapped using the sorting attribute of the asset feature.
    • If the array property is missing, has a null value or an empty array, all mapped asset features are deleted.
    • If there are no mapped asset features during export, the property is either skipped or written using an empty array if it is part of the required keyword in the schema.
  • Schemas of the type object are only mapped when they occur as a sub schema of an array. Otherwise they are considered structural decoration and not mapped at all. Their properties in turn are mapped according to these rules.
    • Inside an array the mapping works along the lines of scalar values, but with a feature value type of None.

Root Level

The root level of the schema defines the entity itself and it is required to be of "type": "object", because entities have to be JSON objects.

  • "cs:asset.type": String value containing censhare asset type id
    • Defines what censhare asset type is used to store to and query from entities belonging to this schema
    • (Optional) By default a new asset type is automatically generated registered
    • Can be set to null to declare the schema a mixin.
  • "cs:$mixin": Array of string containing the schema reference names of the mixins (schema name with suffix -schema.json)
    • The referenced mixins need to already registered on the endpoint
    • See also below.
  • "cs:$no_new_masterdata": true
    • Prevents the automatic creation of master data that is declared in this schema but is not present in the censhare application server
    • (Optional) If not present, the missing master data is automatically created

Mixin

Mixins provide a mechanism for managing common property subsets among multiple schemas. Mixins are similar to schemas as they hold property definitions, but can be included included into regular schemas. The defining difference between a mixin and a schema is that it is not assigned to asset types, but to null, see root level. As a consequence entities can not be based directly on a mixin and there are no entity endpoints for mixins, although they are otherwise managed through the schema endpoint.

When an mixin is included in an entity, see section root level, all property definitions of the mixin are included into the schema, the other parts of the mixin are ignored, including all cs: metadata. Note that duplicate property definitions are not allowed. Declarations of the same property in the mixin and the including schema will lead to the rejection of the schema. Mixins can form inheritance like structures by including other mixins, in which inclusion of the same mixin at several levels is possible.

Mixin properties can be used in queries as they will automatically be replaced by all effective schemas that use this mixin directly or indirectly.

Mixin Example

The following mixin provides the features censhare:asset.name and censhare:asset.id, which are present on all assets:

{
    "cs:asset.type" : null,
    "type" : "object",
    "properties" : {
        "name" : {
            "type" : "string",
            "cs:feature.key" : "censhare:asset.name"
        },
        "id" : {
            "type" : "number",
            "cs:feature.key" : "censhare:asset.id"
        }
    }
}

Assuming the mixin above has been registered under the name asset the following schema text can reference it to inherit its properties:

{
    "cs:$mixin": [
        "asset-schema.json"
    ],
    "cs:asset.type": "text.",
    "type": "object",
    "properties": {
        "content": {
            "cs:storage.item": "master",
            "type": "string"
        }
    }
}

Accessing the effective schema reveals that censhare:asset.name and censhare:asset.id have been included:

{
    "cs:$mixin": [
        "asset-schema.json"
    ],
    "cs:asset.type": "text.",
    "type": "object",
    "properties": {
        "name": {
            "cs:feature.key": "censhare:asset.name",
            "type": "string"
        },
        "id": {
            "cs:feature.key": "censhare:asset.id",
            "type": "number"
        },
        "content": {
            "cs:storage.item": "master",
            "type": "string"
        }
    }
}

Therefor all three properties are included into the entities:

{
    "name": "words.txt",
    "id": 13612,
    "content": "Tips for Creating Content, and Getting It Found."
}

Data-less Object

Property defined as "type": "object" with no additional metadata is considered data-less: it is not stored anywhere, it just provides one level in JSON structure. The actual payload data must be stored somewhere in its properties. When writing JSON output, data-less entities are omitted if empty. For this reason, it is not recommended to declare them as required.

Constant Mapping

Constant string properties that have their value specified using JSON schema "const" or a single value "enum" can be mapped using "cs:$const": true. They are not mapped to/from the data store, but the value is added during export.

Ignore Mapping

Any schema type can be marked using "cs:$ignore": true which is then ignored during mapping, but the validation is still be performed.