Mapping to JSON
Rules for the construction of JSON payloads matching an Aspect Model
For understanding the construction rules, we define the following terms:
-
A Constraint of the Property’s Characteristic defined with a Trait is applied to the characteristic referred in the
samm-c:baseCharacteristic
. -
A Property’s effective data type means the Property’s Characteristic’s
samm:dataType
. -
A data type is scalar, if it is one of the allowed data types, but not a
samm:Entity
.
In order to create JSON payloads that correspond to an Aspect Model, the following rules are applied. The other way round they can also be used to describe a validation algorithm.
-
An Aspect Model is always serialized as an unnamed JSON object.
-
For each Property:
-
If it is marked as optional, it may or may not be included in the payload. If, and only if, the Property is marked as optional and is included in the payload, then its value may be
null
, which is equivalent to it not being included in the payload. -
If the Property’s effective data type is scalar with any date type other than
rdf:langString
, the Property is serialized as${propertyName}: ${value}
where${value}
is the JSON serialization of the respective Property’s value, details on mapping of the data types are given in Data type mappings. The value must adhere to the value range defined by the Property’s effective data type and possible Constraints on the Property’s Characteristic. -
If the Property’s effective data type is scalar with the data type
rdf:langString
, the Property is serialized as a named JSON object (with${propertyName}
being the name of the JSON property), with keys for each available language tag of the Property and the corresponding localized string as the value. -
If the Property’s effective data type is not scalar, it is serialized as a named JSON object (with
${propertyName}
being the name of the JSON property), recursively using the same rules. -
If the Property’s effective data type is an Entity which extends another Entity, it is serialized as a named JSON object (with
${propertyName}
being the name of the JSON property). The Properties included for the Entity, are the Properties from the Entity itself as well as all Properties from the extended Entities, i.e. all Properties from?thisEntity samm:extends* []
. -
If the Property’s Characteristic is a Collection, List, Set or Sorted Set, it is serialized as a named JSON array (with
${propertyName}
being the name of the JSON array property).
-
-
Characteristics defined in the Aspect Model other than the ones mentioned above are not subject to serialization.
-
Operations defined in the Aspect Model are not subject to serialization.
-
Events defined in the Aspect Model are not subject to serialization.
Example
Aspect Model
@prefix : <urn:samm:com.mycompany.myapplication:1.0.0#> .
@prefix samm: <urn:samm:org.eclipse.esmf.samm:meta-model:2.1.0#> .
@prefix samm-c: <urn:samm:org.eclipse.esmf.samm:characteristic:2.1.0#> .
@prefix samm-e: <urn:samm:org.eclipse.esmf.samm:entity:2.1.0#> .
@prefix unit: <urn:samm:org.eclipse.esmf.samm:unit:2.1.0#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
:Movement a samm:Aspect ;
samm:preferredName "movement"@en ;
samm:properties ( :isMoving :speed ) ;
samm:operations ( ) ;
samm:events ( ) .
:isMoving a samm:Property ;
samm:preferredName "is moving"@en ;
samm:characteristic samm-c:Boolean .
:speed a samm:Property ;
samm:preferredName "speed"@en ;
samm:characteristic :Speed ;
samm:exampleValue "0.5"^^xsd:float .
:Speed a samm-c:Measurement ;
samm:preferredName "speed"@en ;
samm:dataType xsd:float ;
samm-c:unit unit:kilometrePerHour .
Data type mappings
A rich type tree is used in an Aspect Model. As JSON offers only a very limited set of data types for primitive type values there are less options on how to represent the data. The mappings are described in the following table.
Aspect Model data type |
Corresponding JSON data type |
|
Core Types |
|
String |
|
Boolean |
|
|
Number |
|
|
Number |
|
IEEE-floating-point numbers |
|
Number |
|
Number |
|
Time and date |
|
String |
|
String |
|
|
String |
|
|
String |
|
Recurring and partial dates |
|
String |
|
String |
|
|
String |
|
|
String |
|
|
String |
|
|
String |
|
|
String |
|
|
String |
|
Limited-range integer numbers |
|
Number |
|
Number |
|
|
Number |
|
|
Number |
|
|
Number |
|
|
Number |
|
|
Number |
|
|
Number |
|
|
Number |
|
|
Number |
|
|
Number |
|
|
Number |
|
Encoded binary data |
|
String |
|
String |
|
Miscellaneous types |
|
String |
|
String |
|
|
A JSON object with a structure as described in the rules above. |
For example, a Property errorMessage
with effective data type rdf:langString
and the value
"Could not load data"@en
would be serialized in the JSON payload as follows:
{
"errorMessage": {
"en": "Could not load data"
}
}
A Property errorMessages
with a Collection Characteristic and effective data type rdf:langString
could yield the payload:
{
"errorMessages": [
{ "en": "Could not load data" },
{ "de": "Konnte Daten nicht laden" }
]
}
Specific payload mappings for Characteristics
This section describes how data payloads look like for specific Characteristics.
Characteristic Name |
Corresponding JSON data type |
|
A JSON object with exactly either a |
The following example Aspect uses samm-c:Either
to express that the Property speedValue
can either return the integer value for speed,
or an Error message (using an Entity), if the value could not be determined (cf. Declaring Either).
So, assuming an Aspect Model has a Property speedProperty
with its samm:characteristic
set to :Result
according to the following definition:
:speedProperty a samm:Property ;
samm:characteristic :Result .
:Result a samm-c:Either ;
samm-c:left :ErrorMessage ;
samm-c:right :SpeedValue .
:ErrorMessage a samm-c:SingleEntity ;
samm:dataType :ErrorEntity .
:SpeedValue a samm-c:Quantifiable ;
samm:dataType xsd:integer .
:ErrorEntity a samm:Entity ;
samm:properties ( :errorCode :errorDescription ) .
the corresponding JSON payload either contains a left
key with the error description:
{
"result": {
"left": {
"errorCode": "...",
"errorDescription": "..."
}
}
}
or it can contain a right
key with the success status:
{
"result": {
"right": {
"status": "..."
}
}
}
In the following example the Property speedProperty
can either return the integer value for speed SpeedValue
,
or an Error
, if the value could not be determined. Error
can either return the samm-c:Text
with simple error text or ErrorMessage
(using an Entity) for details of error like errorCode
and errorDescription
.
So, assuming the Property speedProperty
with samm-characteristics
set to :Result
according to the following definition:
:speedProperty a samm:Property ;
samm:characteristic :Result .
:Result a samm-c:Either ;
samm:description "The result is either an error or a SpeedValue"@en ;
samm-c:left :Error ;
samm-c:right :SpeedValue .
:Error a samm-c:Either ;
samm:description """An error can be either a simple text, or a complex object with separate errorCode and errorDescription"""@en ;
samm-c:left samm-c:Text ;
samm-c:right :ErrorMessage .
:SpeedValue a samm-c:Quantifiable ;
samm:dataType xsd:integer .
:ErrorMessage a samm:Characteristic ;
samm:dataType :ErrorEntity .
:ErrorEntity a samm:Entity ;
samm:properties ( :errorCode :errorDescription ) .
:errorCode a samm:Property ;
samm:characteristic samm-c:Text .
:errorDescription a samm:Property ;
samm:characteristic samm-c:Text .
it can contain right
key with the speed value:
{
"speedProperty": {
"right": 60
}
}
or possible left
key of Error
contains Error message:
{
"speedProperty" : {
"left" : {
"right" : {
"errorDescription" : "...",
"errorCode" : "..."
}
}
}
}
or it can contain right
key of Error
with simple error text:
{
"speedProperty" : {
"left" : {
"left" : "Simple error description..."
}
}
}
If the model is invalid, it might be impossible to build a JSON payload that corresponds to the model.
For example, if a Set of xsd:boolean values has a Length Constraint of samm-c:minValue 3, no valid payload can be constructed.
|
Limitations
Due to the limits in the
represention of numbers in JSON, the maximum integer number that can be used without losing
precision is 2⁵³-1 (defined as
Number.MAX_SAFE_INTEGER).
This means that even if the Aspect Model data type would allow higher or lower values, if they can
not be represented in JSON, they can not be used. Affected data types are the unbounded numeric
types xsd:decimal
, xsd:integer
, xsd:positiveInteger
, xsd:nonNegativeInteger
,
xsd:negativeInteger
, xsd:nonPositiveInteger
and the bounded type xsd:unsignedLong
. The other
numeric types are not affected.