We know that you can automatically serialize anything to a ByteArray and that it’s faster and smaller than XML or JSON, but why is it so much smaller? Today’s article investigates a bit and reveals the secret that makes it such an efficient format and how that can save you a lot of manual work when it comes time to deserialize the ByteArray.

To help investigate, let’s work with a simple Person class:

class Person
{
	var first:String;
	var last:String;
	var mother:Person;
	var father:Person;
}

When serializing to ByteArray with its writeObject function, one of the great features is that it’ll recursively serialize your custom objects and won’t double-encode anything since it supports references/pointers internally. So you can simply do this:

var mother:Person = new Person();
mother.first = "Susan";
mother.last = "Smith";
 
var father:Person = new Person();
father.first = "Bruce";
mother.last = "Smith";
 
var child:Person = new Person();
child.first = "Jimmy";
child.last = "Smith";
child.mother = mother;
child.father = father;
 
bytes.writeObject(new <Person>[child,father,mother]);

There’s no need to worry that the child Person object will store a duplicate copy of the mother and father Person objects. At least that’s what the AMF specification that defines the ByteArray.writeObject/readObject file format says.

How can we test this to observe it in action? Well, let’s make a little test where we give a Person a really long first and last name and then serialize that Person object a bunch of times to the ByteArray:

var reallyLongString:String = "";
for (var i:int = 0; i < 1024; ++i)
{
	reallyLongString += i;
}
 
var person:Person = new Person();
person.first = reallyLongString;
person.last = reallyLongString;
person.mother = person;
 
var bytes:ByteArray = new ByteArray();
for (var i:int = 0; i < 1000000; ++i)
{
	bytes.writeObject(person);
}
 
trace(bytes.length);

If there weren’t support for pointers/references in AMF, this ByteArray would be full of duplicates of reallyLongString and the ByteArray would be huge. Instead, we simply get 3 million bytes. Considering that there are 1 million Person objects and they all have two huge strings, it’s safe to say that AMF is doing a good job at safeguarding against duplicate objects.

As one final test though, let’s see just how far AMF takes this pointer/reference concept. Does ByteArray.readObject preserve them in the AS3 objects it reads back? Here’s one final test that reads back the first two Person objects and checks if each of their mother fields point to the same Person:

bytes.position = 0;
var obj1:Object = bytes.readObject();
var obj2:Object = bytes.readObject();
trace(obj1.mother == obj2.mother);

This will actually print “true”, meaning that the references are preserved all the way through the serialization and deserialization process. This is a really handy feature that makes the AMF format of ByteArray.readObject and ByteArray.writeObject (especially in combination with registerClassAlias) really great to use in comparison to the more common XML and JSON. It’s faster, smaller, and preserves types and references. AMF is definitely worth considering the next time you need to serialize something.

Spot a bug? Have a suggestion or a question? Post a comment!