Wowza Community

JSON encoding of AMFData

I was trying to store AMFData in a db for later resending recently and as part of that I successfully experimented with JSON encoding for storage and transfer. I ended up using the builtin AMFDataObj.serialize and base64-ing it to avoid charset encoding issues with the bits when transferring it around: http://www.wowza.com/forums/showthread.php?p=41720#post41720 , but the JSON encoding did work first (it just took up more space in my db than base64 of raw AMF bytes). Here is the base AMFData JSON encoding function for the benefit of all. It does work to some degree at least, as it did work for my purposes (layered AMFDataArrays in AMFDataObjects and lots of numbers and strings in AMFDataItems), but please post fixes if you come across any bugs in using it, thanks.

// json serialization of wowza amfdata
public static String jsonAMF (AMFData d) throws Exception
{
	StringBuffer sb = new StringBuffer();
	int t = d.getType();

	if (t == AMFData.DATA_TYPE_STRING || t == AMFData.DATA_TYPE_DATE)
	 { sb.append("\"").append(jsonEscape(((AMFDataItem)d).toString())).append("\""); }

	else if (t == AMFData.DATA_TYPE_NUMBER || t == AMFData.DATA_TYPE_BOOLEAN) { sb.append(d); }

	else if (t == AMFData.DATA_TYPE_UNDEFINED || t == AMFData.DATA_TYPE_UNKNOWN
	 || t == AMFData.DATA_TYPE_NULL) { sb.append("null"); }

	// Mixed Array is not a perfect match:
	//  JSON only has string keys, whereas this allows integer keys as well as strings
	else if (t == AMFData.DATA_TYPE_OBJECT || t == AMFData.DATA_TYPE_MIXED_ARRAY)
	{
	        AMFDataObj o = (AMFDataObj)d;
		sb.append("{");
		Iterator i = o.getKeys().iterator();
		boolean notfirst = false;
		while (i.hasNext())
		{
			if (notfirst) { sb.append(","); }
			 else { notfirst = true; }
			String k = (String)i.next();
			sb.append("\"").append(jsonEscape(k)).append("\":");
			sb.append(jsonAMF(o.get(k)));
		}
		sb.append("}");
	}

	else if (t == AMFData.DATA_TYPE_ARRAY)
	{
	        AMFDataArray o = (AMFDataArray)d;
		sb.append("[");
		int i = 1, z = o.size();
		if (z > 0) { sb.append(jsonAMF(o.get(0))); }
		for (; i < z; i++) { sb.append(",");
		 sb.append(jsonAMF(o.get(i))); }
		sb.append("]");
	}

	else { throw new Exception("invalid amf data for json encode! (" + t + ")"); }

	return sb.toString();
}

The jsonEscape function in the code above swaps out invalid json string chars with their escaped versions as per http://json.org/string.gif and is basic but long so I won’t post it.

Since I didn’t want to write a JSON decoding function into AMFData, I just did the json decoding into basic objects on the flash end, sending only the json string data. The decoder comes from adobe labs hosted on google code:

http://code.google.com/p/as3corelib/

For those using the command line flex compiler mxmlc include this with (as3corelib.swc is in the lib dir of the as3corelib.zip you get from the website):

mxmlc -library-path as3corelib.swc ....

And in the flash actionscript, it’s very simple:

import com.adobe.serialization.json.JSON;  // [url]http://code.google.com/p/as3corelib/[/url]
private function deserialize (jsonData:String) :void { process(JSON.decode(jsonData)); }

Enjoy!