Format "Value" (Value-Only Serialization) in JSON Overview of Value-Only Serialization Attributes In many cases, applications using data from Asset Administration Shells already know the Submodel regarding its structure, attributes, and semantics. Consequently, there is not always a need to receive the entire model information, which can be requested separately via Content modifier set to Metadata (see IDTA-01002), in each request since it is constant most of the time. Instead, applications are most likely only interested in the values of the modelled data. Furthermore, having limited processing power or limited bandwidth, one use case of this format is to transfer data as efficiently as possible. Semantics and data might be split into two separate architecture building blocks. For example, a database would suit the needs for querying semantics, while a device would only provide the data at runtime. Two separate requests make it possible to build up a user interface (UI) and show new upcoming values highly efficiently. Values are only available for All subtypes of abstract type DataElement, SubmodelElementList and SubmodelElementCollection resp. for their included SubmodelElements, ReferenceElement, RelationshipElement + AnnotatedRelationshipElement, Entity, BasicEventElement, Submodel. Capabilities and Operations are excluded from the serialization scope since only data containing elements are in the focus. They are consequently omitted in the serialization. Abstract SubmodelElements are not contained in payload. The following rules shall be adhered to when serializing a submodel, a SubmodelElement collection or a SubmodelElement list with the format "Value"[1]: A Submodel or a SubmodelElement collection is serialized as an unnamed JSON object. A SubmodelElement list is serialized as an JSON array. A SubmodelElement is considered a leaf SubmodelElement if it does not contain other SubmodelElements. A leaf SubmodelElement follows the rules for the different SubmodelElements considered in the serialization, as described below. If it is not a leaf element, the serialization rules must be transitively followed until the value is a leaf SubmodelElement. Reference is serialized in format "Normal". SpecificAssetId is serialized in format "Normal". SubmodelElements without a value are not serialized. For each SubmodelElement within the submodel, the SubmodelElement collection or SubmodelElement list: Property is serialized as ${Property/idShort}: ${Property/value} where ${Property/value} is the JSON serialization of the respective property’s value in accordance with the data type to value mapping (see Table 1). MultiLanguageProperty is serialized as named JSON object with ${MultiLanguageProperty/idShort} as the name of the containing JSON property. The JSON object contains an array of JSON objects for each language of the MultiLanguageProperty with the language as name and the corresponding localized string as value of the respective JSON property. The language name is defined as two chars according to ISO 639-1. Range is serialized as named JSON object with ${Range/idShort} as the name of the containing JSON property. The JSON object contains two JSON properties. The first is named "min". The second is named "max". Their corresponding values are ${Range/min} and ${Range/max}. The formerly experimental SubmodelElement Range is invalidated, i.e. will not be supported in future. File and Blob are serialized as named JSON objects with ${File/idShort} or ${Blob/idShort} as the name of the containing JSON property. The JSON object contains two JSON properties. The first refers to the content type named ${File/contentType} resp. ${Blob/contentType}. The latter refers to the value named "value" ${File/value} resp. ${Blob/value}. The resulting ValueOnly object is indistinguishable whether it contains File or Blob attributes. Therefore, the receiver needs to take the type of the target resource into account. Since the receiver knows in advance if a File or a Blob SubmodelElement shall be manipulated, it can parse the transferred Value-Only object accordingly as a File or Blob object. SubmodelElementCollection is serialized as named JSON object with ${SubmodelElementCollection/idShort} as the name of the containing JSON property. The elements contained within the struct, i.e. the elements in SubmodelElementCollection/value, are serialized according to their respective type with ${SubmodelElement/idShort} as the name of the containing JSON property. SubmodelElementList is serialized as a named JSON array with ${SubmodelElementList/idShort} as the name of the containing JSON property. The elements in the JSON array, i.e. the elements in SubmodelElementList/value, are the ValueOnly serializations of the elements contained in the SubmodelElementList while preserving the order, i.e. index n in the JSON array is the ValueOnly serialization of the element at index n of the SubmodelElementList. ReferenceElement is serialized as ${ReferenceElement/idShort}: ${ReferenceElement/value} where ${ReferenceElement/value} is the serialization of the Reference class in format "Normal" (see above). RelationshipElement is serialized as named JSON object with ${RelationshipElement/idShort} as the name of the containing JSON property. The JSON object contains two JSON properties. The first is named "first". The second is named "second". Their corresponding values are ${RelationshipElement/first} resp. ${Relationship/second}. The values are serialized according to the serialization of a ReferenceElement (see above). AnnotatedRelationshipElement is serialized according to the serialization of a RelationshipElement (see above). Additionally, a third named JSON object is introduced with "annotations" as the name of the containing JSON property. The value is ${AnnotatedRelationshipElement/annotations}. The values of the array items are serialized depending on the type of the annotation data element. Annotations are optional. Entity is serialized as named JSON object with ${Entity/idShort} as the name of the containing JSON property. The JSON object contains four JSON properties. The first is named "statements" ${Entity/statements} and contains an array of the serialized SubmodelElements according to their respective serialization mentioned in this clause. The second is named "globalAssetId" and the third "specificAssetIds". Either a "globalAssetId" value or a "specificAssetIds" value shall exist. The other attributes are optional. "specificAssetIds" is an array of objects serializing SpecificAssetId. A single SpecificAssetId in the array corresponds to the serialization of the SpecificAssetId class in format "Normal". The forth property is named "entityType" and contains a string representation of ${Entity/entityType}. statements and the entityType are optional. BasicEventElement is serialized as named JSON object with ${BasicEventElement/idShort} as the name of the containing JSON property. The JSON object contains one JSON property named "observed" with the corresponding value of ${BasicEventElement/observed} as the standard serialization of the Reference class. The following rules shall be adhered to when serializing a single SubmodelElement with the format "Value": Property is serialized as ${Property/value} where ${Property/value} is serialized as described above. MultiLanguageProperty is serialized as JSON object. The JSON object is serialized as described above. Range is serialized as JSON object. The JSON object is serialized as described above. The formerly experimental SubmodelElement Range is invalidated, i.e. will not be supported in future. File and Blob are serialized as JSON objects. The JSON object is serialized as described above. ReferenceElement is serialized as ${ReferenceElement/value} where ${ReferenceElement/value} is is serialized as described above. RelationshipElement is serialized as JSON object. The JSON object is serialized as described above. AnnotatedRelationshipElement is serialized as JSON object. The JSON object is serialized as described above. Entity is serialized as JSON object. The JSON object is serialized as described above. BasicEventElement is serialized as JSON object. The JSON object is serialized as described above. SubmodelElements defined in the Submodel other than the ones mentioned above are not subject to the Value-Only serialization. Optional elements (like for example globalAssetId for an Entity SubmodelElement) with no value shall be omitted in the serialization. Note: Elements within a SubmodelElementList are neither optional or mandatory per se. So in Value-Only all elements within a SubmodelElementList shall be displayed even if they are empty (handled as if they are mandatory). Rationale: index of elements within a SubmodelElementList shall be identical in Normal and Value-Only format. Data type to value mapping The serialization of SubmodelElement values is described in the following table. The left column "Data Type" shows the data types which can be used for SubmodelElement values. The data types are defined according to the W3C XML Schema (https://www.w3.org/TR/xmlschema-2/#built-in-datatypes and https://www.w3.org/TR/xmlschema-2/#built-in-derived). "Value Range" further explains the possible range of data values for this data type. The right column comprises related examples of the serialization of SubmodelElement values. Table 1. Mapping of Data Types in ValueOnly-Serialization[2] Data Type JSON Type Value Range Sample Values Core Types xs:string string Character string "Hello world", "Καλημέρα κόσμε", "コンニチハ" xs:boolean boolean true, false true, false xs:decimal number Arbitrary-precision decimal numbers -1.23, 126789672374892739424.543233, 100000.00, 210 xs:integer number Arbitrary-size integer numbers -1, 0, 126789675432332938792837429837429837429, 100000 IEEE-floating-point numbers xs:double number 64-bit floating point numbers -1.0, -0.0, 0.0, 234.567e8, 234.567e+8, 234.567e-8 xs:float number 32-bit floating point numbers -1.0, -0.0, 0.0, 234.567e8, 234.567e+8, 234.567e-8 Time and data xs:date string Dates (yyyy-mm-dd) with or without time zone "2000-01-01","2000-01-01Z", "2000-01-01+12:05" xs:time string Times (hh:mm:ss.sss…) with or without time zone "14:23:00", "14:23:00.527634Z", "14:23:00+03:00" xs:dateTime string Date and time with or without time zone "2000-01-01T14:23:00", "2000-01-01T14:23:00.66372+14:00" xs:dateTimeStamp string Date and time with required time zone "2000-01-01T14:23:00.66372+14:00" Recurring and partial dates xs:gYear string Gregorian calendar year "2000", "2000+03:00" xs:gMonth string Gregorian calendar month "--04", "--04+03:00" xs:gDay string Gregorian calendar day of the month "---04", "---04+03:00" xs:gYearMonth string Gregorian calendar year and month "2000-01", "2000-01+03:00" xs:gMonthDay string Gregorian calendar month and day "--01-01", "--01-01+03:00" xs:duration string Duration of time "P30D", "-P1Y2M3DT1H", "PT1H5M0S" xs:yearMonthDuration string Duration of time (months and years only) "P10M", 'P5Y2M" xs:dayTimeDuration string Duration of time (days, hours, minutes, seconds only) "P30D", 'P1DT5H", 'PT1H5M0S" Limited-range integer numbers xs:byte number -128…+127 (8 bit) -1, 0, 127 xs:short number -32768…+32767 (16 bit) -1, 0, 32767 xs:int number 2147483648…+2147483647 (32 bit) -1, 0, 2147483647 xs:long number -9223372036854775808…+9223372036854775807 (64 bit) -1, 0, 9223372036854775807 xs:unsignedByte number 0…255 (8 bit) 0, 1, 255 xs:unsignedShort number 0…65535 (16 bit) 0, 1, 65535 xs:unsignedInt number 0…4294967295 (32 bit) 0, 1, 4294967295 xs:unsignedLong number 0…18446744073709551615 (64 bit) 0, 1, 18446744073709551615 xs:positiveInteger number Integer numbers >0 1, 7345683746578364857368475638745 xs:nonNegativeInteger number Integer numbers ≥0 0, 1, 7345683746578364857368475638745 xs:negativeInteger number Integer numbers <0 -1, -23487263847628376482736487263847 xs:nonPositiveInteger number Integer numbers ≤0 -1, 0, -93845837498573987498798987394 Encoded binary data xs:hexBinary string Hex-encoded binary data "6b756d6f77617368657265" xs:base64Binary string base64-encoded binary data SGVsbG8sIFdvcmxkIQ== Miscellaneous types xs:anyURI string Absolute or relative URIs and IRIs "http://customer.com/demo/aas/1/1/1234859590", "urn:example:company:1.0.0" rdf:langString string Strings with language tags "'Hello'@en", "'Hallo'@de" Note: the examples are written in RDF/Turtle syntax, and only "Hello" and "Hallo" are the actual values. The following types defined by the XSD and RDF specifications are explicitly omitted for serialization - they are not element of DataTypeDefXsd or DataTypeDefRdf: xs:language, xs:normalizedString, xs:token, xs:NMTOKEN, xs:Name, xs:NCName, xs:QName, xs:ENTITY, xs:ID, xs:IDREF, xs:NOTATION, xs:IDREFS, xs:ENTITIES, xs:NMTOKENS, rdf:HTML and rdf:XMLLiteral. Note 1: due to the limits in the representation of numbers in JSON, the maximum integer number that can be used without losing precision is 253-1 (defined as Number.MAX_SAFE_INTEGER). Even if the used data type would allow higher or lower values, they cannot be used if they cannot be represented in JSON. Affected data types are unbounded numeric types xs:decimal, xs:integer, xs:positiveInteger, xs:nonNegativeInteger, xs:negativeInteger, xs:nonPositiveInteger and the bounded type xs:unsignedLong. Other numeric types are not affected. [3] Note 2: the ValueOnly-serialization uses JSON native data types, AAS in general uses XML Schema Built-in Datatypes for Simple Data Types and ValueDataType. In case of booleans, JSON accepts only literals true and false, whereas xs:boolean also accepts 1 and 0, respectively. In case of double, JSON number is used in ValueOnly, but JSON number does not support INF/-INF (positive Infinity/negative), which is supported by xs:double. Furthermore, NaN (Not a Number) is also not supported. (See https://datatracker.ietf.org/doc/html/rfc8259#section-6) Note 3: language-tagged strings (rdf:langString) containing single quotes (‘) or double quotes (") are not supported. Note 4: Roundtrip conversion from "Normal" to "ValueOnly" format may not result in the original payload because "Normal" is using string whereas "ValueOnly" is using the JSON type closest to the xsd datatype (see Table 1). Example Value-Only serialization for a Submodel The following example shows the JSON Value-Only serialization for a Submodel with name "Example" and two direct SubmodelElements "ProductClassifications" and "MaxRotationSpeed". "ProductClassifications" is represented by a SubmodelElementList with SubmodelElementCollections as its elements. Each of the SubmodelCollections has two mandatory elements "ProductClassificationSystem" and "ProductClassId" and one optional element "ProductClassificationVersion". All of these elements have data type "xs:string". "MaxRotationSpeed" is a property with data type "xs:int". { "ProductClassifications": [ { "ProductClassificationSystem": "ECLASS", "ProductClassId": "27-01-88-77", "ProductClassificationVersion": "9.0" }, { "ProductClassificationSystem": "IEC CDD", "ProductClassId": "0112/2///61987#ABA827#003" } ], "MaxRotationSpeed": 5000 } The JSON Value-Only serialization for the element "ProductClassifications", a SubmodelElementList, within the Submodel above looks like this: [ { "ProductClassificationSystem": "ECLASS", "ProductClassId": "27-01-88-77", "ProductClassificationVersion": "9.0" }, { "ProductClassificationSystem": "IEC CDD", "ProductClassId": "0112/2///61987#ABA827#003" } ] The JSON Value-Only serialization for the first element, a SubmodelElementCollection, within the "ProductClassifications" list above looks like this: { "ProductClassificationSystem": "ECLASS", "ProductClassId": "27-01-88-77", "ProductClassificationVersion": "9.0" } The JSON Value-Only serialization for the Property "MaxRotationSpeed" of the Submodel above looks like this: 5000 The Format "Normal" in comparison to this Value-Only serialization of the property "MaxRotationSpeed" would look like this: { "idShort": "MaxRotationSpeed", "semanticId": { "type": "ExternalReference", "keys": [ { "type": "GlobalReference", "value": "0173-1#02-BAA120#008" } ] }, "modelType": "Property", "valueType": "xs:int", "value": "5000" } Example Value-Only serialization for a SubmodelElementCollection with non-serialized elements The following SubmodelElementCollection in simplified notation { myCollection: { "prop1": string, "capability1": Capability, "operation1": Operation, "list": SubmodelElementList(typeofElements:Operation) } } is serialized to { "prop1": "value of prop1" } in Format "Value". Since Capability and Operation are not part of Value-Only serialization they are omitted. Also a List containing elements that are omitted is omitted. This is even the case if the SubmodelElementList is mandatory. Note: Similar handling is required in case there are access rules disallowing access to specific SubmodelElements: The protected elements shall not be serialized. Examples Value-Only serialization for all SubmodelElement types In the following examples for Value-Only serializations for all SubmodelElement types are given. Property For a single Property named "MaxRotationSpeed", the value-Only payload is minimized to the following (assuming its value is 5000): 5000 SubmodelElementCollection For a SubmodelElementCollection named "ProductClassification" or being part of a list "ProductionClassifications", the Value-Only payload is minimized to the following, i.e. the name of the SubmodelElementCollection or its index in the list is not part of the Value-Only serialization: { "ProductClassificationSystem": "ECLASS", "ProductClassId": "27-01-88-77", "ProductClassificationVersion": "9.0" } SubmodelElementList For a SubmodelElementList named "Authors" with string Properties as its value, the Value-Only payload is minimized to the following (idShort of values within a SubmodelElementList are ignored):[4]: [ "Martha", "Jonathan", "Clark" ] For a SubmodelElementList named "ListOfLists" with three SubmodelElementLists with xs:string values as its value, the Value-Only payload is minimized to the following (empty lists are included): [ [ "A" ], [], [ "B", "C" ] ] For a SubmodelElementList named "ListOfSMC" with three SubmodelElementCollections as its value (their properties "A" and "B" are both optional), the Value-Only payload is minimized to the following (empty collections are included): [ { "A": 1 }, {}, { "A": 5, "B": "new" } ] For a SubmodelElementList named "ListOfProp" "empty" properties are included as "null". [ 1, null, 5 ] MultiLanguageProperty For a MultiLanguageProperty the Value-Only payload is minimized to the following: [ {"de": "Das ist ein deutscher Bezeichner"}, {"en": "That's an English label"} ] Range The formerly experimental SubmodelElement Range is invalidated, i.e. will not be supported in future. For a Range named "TorqueRange", the Value-Only payload is minimized to the following: { "min": 3, "max": 15 } ReferenceElement For a ReferenceElement named "MaxRotationSpeedReference", the Value-Only payload is minimized to the following: { "type": "ExternalReference", "keys": [ { "type": "GlobalReference", "value": "0173-1#02-BAA120#008" } ] } File For a File named "Document", the Value-Only payload is minimized to the following: { "contentType": "application/pdf", "value": "https://myDomain/SafetyInstructions.pdf" } Blob For a Blob named "Library", there are two possibilities for the Value-Only payload. In case the Blob value - that can be very large - shall not be part of the payload, the payload is minimized to the following[5]: { "contentType": "application/octet-stream" } In the second case the Blob value is part of the payload.[6], there is an additional attribute containing the base64-encoded value: { "contentType": "application/octet-stream", "value": "VGhpcyBpcyBteSBibG9i" } RelationshipElement For a RelationshipElement named "CurrentFlowsFrom", the Value-Only payload is minimized to the following: { "first": { "type": "ModelReference", "keys": [ { "type": "Submodel", "value": "http://customer.com/demo/aas/1/1/1234859590" }, { "type": "Property", "value": "PlusPole" } ] }, "second": { "type": "ModelReference", "keys": [ { "type": "Submodel", "value": "http://customer.com/demo/aas/1/0/1234859123490" }, { "type": "Property", "value": "MinusPole" } ] } } AnnotatedRelationshipElement For an AnnotatedRelationshipElement named "CurrentFlowFrom", with an annotated Property-DataElement "AppliedRule", the Value-Only-payload is minimized to the following: { "first": { "type": "ModelReference", "keys": [ { "type": "Submodel", "value": "http://customer.com/demo/aas/1/1/1234859590" }, { "type": "Property", "value": "PlusPole" } ] }, "second": { "type": "ModelReference", "keys": [ { "type": "Submodel", "value": "http://customer.com/demo/aas/1/0/1234859123490" }, { "type": "Property", "value": "MinusPole" } ] }, "annotations": [ { "AppliedRule": "TechnicalCurrentFlowDirection" } ] } Entity For an Entity named "MySubAssetEntity", the Value-Only-payload is minimized to the following: { "statements": { "MaxRotationSpeed": 5000 }, "entityType": "SelfManagedEntity", "globalAssetId": { "type": "ExternalReference", "keys": [ { "type": "GlobalReference", "value": "http://customer.com/demo/asset/1/1/MySubAsset" } ] } } BasicEventElement For a BasicEventElement named "MyBasicEvent", the Value-Only-payload is minimized to the following: { "observed": { "type": "ModelReference", "keys": [ { "type": "Submodel", "value": "http://customer.com/demo/aas/1/1/1234859590" }, { "type": "Property", "value": "MaxRotation" } ] } } Value-Only for Invoking of Operations Although Operations are omitted in Value-Only there is one exception: invoking of operations. Note: Operation/inputVariables is renamed to "inputArguments" etc. in the JSON Value-Only Schema. Same holds for the specification of the invoke operations in IDTA-01002 (InvokeOperationSync and InvokeOperationAsync). This would be the payload conformant to the metamodel specification as would be used in a Submodel Template Specification: { "idShort": "add", "inputVariables": [ { "value": { "idShort": "arg1", "modelType": "Property", "valueType": "xs:int" } }, { "value": { "idShort": "arg2", "modelType": "Property", "valueType": "xs:int" } } ], "outputVariables": [ { "value": { "idShort": "out1", "modelType": "Property" "valueType": "xs:int" } } ], "modelType": "Operation" } This would be the payload as defined in the API OpenAPI specification for the invocation of an operation (InvokeOperationSync with data type OperationRequest ) with idShort "add" in Format "Normal" with input arguments "arg1" and "arg2" of type "xs:int" and a return argument with name "out1" of type "xsd:int": { "inputArguments": [ { "value": { "idShort": "arg1", "modelType": "Property", "valueType": "xs:int", "value": "5000" } }, { "value": { "idShort": "arg2", "modelType": "Property", "valueType": "xs:int", "value": "2" } } ] } The simplified operation result (for the complete payload see IDTA-01002) would look like this: { "outputArguments": [ { "value": { "idShort": "out1", "modelType": "Property", "valueType": "xs:int", "value": "5002" } } ] } Arguments in an operation are handled like a SubmodelElementCollection, not like a SubmodelElementList because they may differ in type and semantics. The arguments in an operation are not ordered. When invoking the same operation in Value-Only format the request body would therefore look like this: { "inputArguments": { "arg1": 5000, "arg2": 2 } } with return object { "outputArguments": { "out1": 5002 } } 1. see SerializationModifier in Part 2 - IDTA-01002 - of the Specification of the Asset Administration Shell 2. cf. https://eclipse-esmf.github.io/samm-specification/2.0.0/datatypes.html with minor changes 3. cf. https://eclipse-esmf.github.io/samm-specification/2.0.0/payloads.html (with adjustments for +/-INF, NaN, and language-typed literal support) 4. The Value-Only serialization of the product classification example can be seen above 5. for the API a special JSON query parameter, the SerializationModifier Extent, is set to WithoutBLOBValue for this case (see IDTA-01002) 6. in this case the JSON query parameter SerializationModifier Extent is set to WithBlobValue (see IDTA-01002)