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 exceptnull
and optionallynull
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
andpattern
are supported. - For schemas that are of the type
object
, all properties must be specified using sub schemas either with theproperties
keyword in general or with thepatternProperties
keyword for some special mappings. The keywordsmaxProperties
,minProperties
,required
,additionalProperties
,dependencies
andpropertyNames
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 keyworditems
and a single sub schema. The sub schema must not be of the typearray
itself. The keywordadditionalItems
is not supported. The keywordsmaxItems
,minItems
,uniqueItems
andcontains
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
- This is the
"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
anddescription
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)
andBoolean
for the respective JSON schema typesstring
,integer
,number
andboolean
. - When a set of enumeration values is specified using the keywords
enum
orconst
for the schema typestring
orinteger
, a feature of the value typeValue list (String)
with the appropriate values is created. - The feature name and description are derived from the JSON schema properties
title
anddescription
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 anarray
. 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
.
- Inside an array the mapping works along the lines of scalar values, but with a feature value type of
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.