Breaking Flash references through serialization

Here is to Google: this article needs to be found by As3 Flash and Flex programmers on the keywords: serialization, JSON, encoding, decoding,  referencing, object referencing, breaking referencing and complicated objects, Resistance is futile. Programming, actionscript. Flash hack, and the final way to un-reference objects in flash.

So here is the git of it; when you want to break references in as3 for a copy or a clone you usually need to get the stuff out of an object and put it back in again; this is hard with complicated objects, but luckily this exactly the same as serialization! for instance through JSON, which is already available in the neatly packed library Casalib

So your copy can be written as:

var copyObject = JSON.decode(JSON.encode( originalObject ))

Well now. I intended to write this in such a way that everybody would be able to understand this, but after a few days of pondering, I’ve decided that that would never work. So I’ll try to keep it brief and interesting, but if you have no idea what as3 is, or referencing for that matter; I’m not sure you’ll get this. Still what I’m writing here is about sheer brilliance and beautiful insight AND I have a picture of the Alien Love Messiah:

This picture expresses how I feel when writing as3

This picture expresses how I feel when writing as3

As most of the readers that are left after that introduction, and the picture know; Actionscript 3 -and Flash in particular- is a referencing programming language. In fact Flash references itself out of it’s mind. In short this means that if I were to enter;

var someVar:Object = { foo: "123", bar "abc" };
var someOtherVar:String = someVar.foo;
someOtherVar = "456";

I am actually referencing and changing the first Object I made; which means that after execution of this code I have changed ‘foo’ in ’somevar’, even though it looks like I copied it in the second line, with ’someOtherVar’. Which I didn’t because flash is referencing, and not rewriting the variable. Or, the second line of code points to the memory address of the first variable and that’s it.

In most cases that is well and fine, it allows you to modify variables on the go without cluttering your memory with all kinds of rubbish-copies you don’t address anymore. But in some cases it’s a pane in the ass. Let’s say you are setting a couple of templates, of which you want to pull copies to actually use in your code. Can’t do that, the copy you run is a reference and will thus alter the original variable.

If you try and Google this problem you are likely to find some blog that describes a method where they write small functions that takes the object apart into strings and then re-assembles them as objects, or even using byte-arrays.

Simple version, with array:

function parse(string) {
	escapestring = escape(string)
	teststring = escapestring.split('%0D%0A').join('%0D');
	return(unescape(teststring))
}

This is nasty and dirty though; we shouldn’t be doing this anyway. Or rather, we shouldn’t have to do it this way.

The array-trick works, but if you run into more complicated objects, you find yourself writing pretty complex parses before you have made your object into a string, and re-objectified it again. You see, my data object looks something like:

[
	[
		{
			"name": "Braderie",
			"info": "In een willekeurige stad is een Braderie",
			"img": "someurl/pic.jpg"
		},

		{ "startTime":0, "actions": [ "setRandomCity", { "name": "testCity" } ] },
		{ "startTime":20, "actions": [ "withAllCities", { "freq": 0.6 } ] },
		{ "startTime":21, "actions": [ "withRandomCity" , { "name": "testCity", "size": "*1000", "freq": 0.01 } ] },
		{ "startTime":2000, "actions": [ "withAllCities", { "freq": 0.01 } ] },
		{ "startTime":2020, "actions": [ "withRandomCity", { "name": "testCity", "size": "*0.001", "freq": 1.5 } ] },
		{ "startTime":2000, "actions": [ "withRandomCity", { "name": "testCity", "freq": 0.01 } ] }
	],

	[] //..&c

Which are, as you can see, nested objects within arrays, with nested arrays, with nested objects again. This would turn out to be an enormous iterative function to make it into a string, and build it back again.

Searching even more on the internet I came across a utility class in the flex framework called mx.ObjectUtil which basically gives you ‘utilities’ that copy an object and can dump it to a string. Which is nice, but as I hate flex even more then I hate regular flash, and on this craptop I can’t get the .swc files to compile.  So what to do?

Actually the last reference to the as2 split.join stuff got me thinking; and I was peeking in the mx.ObjectUtil class, which looks remarkable like a serialization class. And serialization is available through the much more common Casalib libraries as part of  the JSON classes. And what is JSON apart from a serialization tool for complex classes ?!

So why not rewrite the split.join through an decode(encode) … tada:

var copyObject = JSON.decode(JSON.encode( originalObject ))

And there you have it, all object references broken, a completely new and nice clean object in only 1 single line of code. I rule. Flowers and good wishes can be posted in the comments :)

Posted: February 6th, 2011
Categories: general, media, nerd, research, technology, web, work
Tags: , , , , , , , , , ,
Comments: No Comments.













2 + = eight