Out-dated AMF3 Data Types

Simple Data Types

Note: This topic is included for backward compatibility purposes only. It describes an out-dated method of XML serialization. If your Java settings are correctly configured and you are using Silk Performer version 2009 or later, you may safely ignore this topic. Usage of the JVM requires the configuration of Flex/AMF3 application-specific custom JAR files that contain classes that are necessary for the serialization of code into correct XML representation. When these JAR files are missing, the translation DLL uses the method of XML serialization described in this topic.

Here are four simple data types that are provided by AMF3. In the binary protocol, each of these data types is transmitted as a 1-byte type marker. The corresponding XML tags for each data type are included in parenthesis.

  • Undefined (<Undefined></Undefined>)
  • Null (<Null></Null>)
  • False (<False></False>)
  • True (<True></True>)

Integer

Integers in AMF3 are serialized as variable-length 29-bit unsigned integers. The variable-length format ensures that integers take up as little space as necessary. In XML format, integers look like this:
<Integer>123456</Integer>

The integer data type is encoded as a 1-byte type marker, followed by up to 4 bytes that encode the integer using the variable length format. Besides their use as a data type, variable-length integers are used in other places within the protocol.

Double

A double stores an 8-byte double precision floating point value as defined in IEEE 754. This is the data type that many programming languages refer to as a double. In XML format, doubles look like this:
<Double>3.14159</Double>

In the binary format, doubles are encoded as 1-byte type markers followed by 8 bytes that contain the double value.

String

Strings are used to store all types of UTF-8-encoded string data. Besides their use as a data type, strings are also used to specify string data, such as classes or member names. All string values in an AMF3 data stream are put into a reference table which is typically generated when AMF3 or XML data is parsed.

A string can either be encoded as a string value or as a string reference. A string reference refers to a previous occurrence of its number in the string reference table. This feature is used to save space when the same string value occurs several times in a single AMF3 data stream.

In XML format, a string looks like this:
<String>Hello, World!</String>
When string references are used, the referenced string is marked with a reference ID (in the form of an attribute), and the string reference refers to the reference ID:
<String val-refId="#0">This string is referenced</String>
<String val-ref="#0"></String>

XML and XMLDocument

AMF3 provides two data types to encode XML data: XMLDocument, which represents a Flash legacy data type, and XML, which is a newer XML type. Both data types encode XML as strings. The difference is that these strings are not registered in the string reference table. They are registered in the object reference table.

Note: With the XML format, the actual XML content must be XML-encoded. Due to a limitation with Silk Performer's XML parser, it is currently not possible to use XML CDATA sections to notate such data.
<Xml>&lt;Data&gt;some data&lt;/Data&gt;</Xml>
<XmlDoc>&lt;Data&gt;some more data&lt;/Data&gt;</XmlDoc>

As with strings, XML data can be referenced to save space:

<Xml refId="data">&lt;Data&gt;foobar&lt;/Data&gt;</Xml>
<Xml ref="data"></Xml>

Date

In AMF3, the date is encoded as the number of milliseconds elapsed since January 1st 1970, 00:00, in the UTC timezone. The number of milliseconds is encoded as a double. Dates also support references, and each date is registered in the object reference table.

<Date>2007-02-18 11:29:00.000</Date>
<Date refId="newmillenium">2000-01-01 00:00:00.000</Date>
<Date ref="newmillenium"></Date>

Array

Arrays in AMF3 cover two types of data structures: standard arrays, where each element is identified by an index number, and associative arrays, where each element is identified by a key (in the case of AMF3, this is always a string). In the binary representation of an array, the associative portion of the array is listed first. This is followed by a separator (an empty string) and finally the dense portion of the array (the standard array elements).

In XML representation, the elements of an associative array are marked by their name attributes. Generally, arrays are not bound to a specific type, which means that you can put any data type in them, including different data types.

	<Array>
		<Integer name="number1">23</Integer>
		<Integer name="number2">42</Integer>
		<String name="username">EMEA\johndoe</String>
		<Date>2008-02-17 13:47:13.000</Date>
		<Undefined></Undefined>
	</Array>

In the above example there is an array with three elements that have a name attribute (meaning they belong to the associative portion of the array) and two elements that do not have a name attribute, which means that they belong to the dense portion of the array.

As with other data types, arrays can be referenced; their elements can be referenced; even their elements’ names can be referenced:

	<Array>
		<String name="foo" name-refId="#0">bar</String>
		<String val-ref="#0"></String>
	</Array>

In this example, there is an array with two string elements. The first element has the name foo and the value bar. The second element has no name, but references the string with the string reference table ID #0 (the string foo).

Arrays themselves are registered in the object reference table.

Object

Objects are the most powerful data type within AMF3. There are several subtypes of classes that you need to be aware of. What all object types have in common is that they bear a class name.

Object Traits

The traits of an object are its member names, plus information indicating if an object is dynamic or externalizable.

An object with traits contains a list of member names followed by the corresponding members. In binary format, member names are encoded as strings without type markers. The number of member names is encoded in an additional field of flags that also contains information about the object’s sub type. Following the members, an optional, additional list of dynamic members, each preceded by their respective member name, is included. The list of dynamic members is only included if the dynamic flag is set to true and terminated by an empty string.

	<Object classname="testclass">
		<Member>strFirstName</Member>
		<Member>strSurname</Member>
		<String>John</String>
		<String>Doe</String>
	</Object>

	<Object classname="testclass2" dynamic="true">
		<Integer name="answer">42</Integer>
	</Object>

Object References

Objects can be directly referenced because they are registered in the objects reference table.

<Object classname="testclass3" dynamic="true" refId="#0">
	<Integer name="answer">42</Integer>
</Object>
<Object ref="#0"></Object>

Traits References

Each object of subtype object traits or externalizable traits is not only added to the objects reference table, but also to the traits reference table. Other objects can then refer to the traits of these objects. This means that such an object does not need to come with the list of members and the object flags by itself, but only with the actual members.

<Object classname="nameclass" traits-refId="name">
		<Member>userid</Member>
		<Member>firstName</Member>
		<Member>lastName</Member>
		<String>jdoe</String>
		<String>John</String>
		<String>Doe</String>
	</Object>
	<Object traits-ref="name">
		<String>mmustermann</String>
		<String>Max</String>
		<String>Mustermann</String>
	</Object>

Externalizable Traits

Externalizable traits contain the binary representation of an object, an indeterminate number of bytes serialized in an unknown format. The format depends on the class that serializes and deserializes this data. The class also has to know how many bytes it has to consume from the byte stream.

Silk Performer provides support for the three most common classes:

  • flex.messaging.io.ArrayCollection
  • flex.messaging.io.ArrayList
  • flex.messaging.io.ObjectProxy

According to Adobe, these three classes are the most common, and are encoded as AMF3. This means that these three classes are parsed like normal arrays or objects, respectively.

In case a class other than these three is found, it is assumed that all bytes up to the end of the stream belong to the externalizable traits. The content of such an unknown externalizable trait is stored as Base64-encoded data.

<Object classname="flex.messaging.io.ArrayCollection" externalizable="true">
<Array>
<Integer>1</Integer>
<Integer>2</Integer>
<Integer>3</Integer>
<Integer>4</Integer>
</Array>
</Object>

<Object classname="flex.messaging.io.ArrayList" externalizable="true">
<Array>
<String>hugo</String>
<String>hugo2</String>
</Array>
</Object>

<Object classname="flex.messaging.io.ObjectProxy" externalizable="true">
<Object classname="" dynamic="true">
<String name="ssnum">555-55-5555</String>
<String name="name">Tyler</String>
<Integer name="age">5</Integer>
</Object>
</Object>

	<Object classname="test" externalizable="true">SGVsbG8sIHdvcmxk</Object>

ByteArray

A ByteArray holds an array of bytes. In XML representation, binary data is encoded in Base64 format.

ByteArrays are registered in the object reference table.

<ByteArray>SGVsbG8sIHdvcmxk</ByteArray>

References

Three different reference tables are used. The following list offers an overview of which data types are registered in which reference table.

String Reference Table:

  • String
  • Class names (not an actual data type)
  • Member names (not an actual data type)
  • Value name of elements of the associative portion of an array (not an actual data type)

Object Reference Table:

  • Object
  • Date
  • Array
  • ByteArray
  • XML
  • XmlDocument

Traits Reference Table:

  • Object traits
  • Externalizable traits

Not registered in any reference table:

  • Undefined
  • Null
  • False
  • True
  • Integer
  • Double

Reference IDs are generated by the AMF3 parser. However in hand-written XML documents, you can use custom reference IDs:

<String val-refId="username">EMEA\johndoe</String>
<String val-ref="username"></String>
Note: Custom reference IDs are lost when an XML document is transformed from XML to AMF3 and back to XML because the AMF3 generator simply looks up the reference table position using the reference ID string and only encodes the position in the AMF3. When parsing such a generated AMF3 data stream, the parser no longer has the information about the custom reference IDs. It generates reference IDs that begin with # and a continuous number that directly reflects the position in the string reference table.