Structures with optional fields shall be encoded as JSON objects as shown in Table 45.
Note that JSON objects are unordered sets of name-value pairs. The order specified by the DataTypeDefinition is not preserved when a Structure is serialized in JSON. The EncodingMask may not appear as the first field.
In the VerboseEncoding the bits in the EncodingMask are determined by the presence of a field in the JSON object. In the CompactEncoding, EncodingMask indicates which fields are specified because fields are omitted because they have a default value.
Table 45 – JSON Object Definition for a Structures with Optional Fields
Name |
Description |
EncodingMask |
A bit mask indicating what fields are encoded in the structure (see 5.2.7) This mask is encoded as a JSON number. The bits are sequentially assigned to optional fields in the order that they are defined. This field is omitted in the VerboseEncoding |
<FieldName> |
The field in structure encoded according to the rules defined for their DataType. One entry may exist for each mandatory field and each optional field that is present. |
Fields which are NULL or have a default value shall be encoded using the rules shown in Table 46.
Table 46 – JSON Encoding Rules for Structures with Optional Fields
Field Value |
Field Type |
Compact |
Verbose |
NULL |
Mandatory |
Omitted |
JSON null |
Default Value |
Mandatory |
Omitted |
Default Value |
NULL |
Optional (Present) |
Omitted |
JSON null |
Default Value |
Optional (Present) |
Omitted |
Default Value |
NULL |
Optional (Omitted) |
Omitted |
Omitted |
Default Value |
Optional (Omitted) |
Omitted |
Omitted |
If a Structure with optional fields is subtyped, the subtypes extend the EncodingMask defined for the parent.
The following is an example of a structure with optional fields using C++ syntax:
struct TypeA
{
Int32 X;
Int32* O1;
SByte Y;
Int32* O2;
};
O1 and O2 are optional fields where a NULL indicates that the field is not present.
Assume that O1 is not specified and the value of O2 is 0.
The CompactEncoding would be:
{ "EncodingMask": 2, "X": 1, "Y": 2 }
Where decoders would assign the default value of 0 to O2 since the mask bit is set even though the field was omitted (this is the behaviour defined for the Int32 DataType). Decoders would mark O1 as ‘not specified’.
The VerboseEncoding would be:
{ "X": 1, "Y": 2, "O2": 0 }
Encoders, when allowed by the DevelopmentPlatform, should write the EncodingMask first. Decoders shall accept the EncodingMask in any position.
Code generators should ensure that the special field names (UaType, UaTypeId and EncodingMask) are not permitted in Structures with option field.