In some instances when JSON is the only available communication protocol, we all know full well about it’s limitations especially when it comes to preserving type or saving state. But what if you were in a closed-loop system where you could simply save what the front-end end would send? In a Flex environment this is still somewhat trivial since you can still use the [RemoteClass] metatag even without an RPC-based mediary like LCDS.

In Flex 4.5 using the Adobe extension to JSON the following will work. In 4.6+ it gets a little harder since the JSON class is now a top-level object – which makes overriding private / modifying protected and/or static methods nearly impossible.

Modifying the encoder entails when encountering complex types that are not just anonymous Objects, if that’s the case then we can prefix the fully qualified class name before the bracket, and do the reverse in the decoder.

package
{

import JSONPlusEncoder;
import JSONPlusDecoder;

public class JSONPlus
{

public static const FQCN_IDENTIFIER:String = ‘fqcn’;

public static function encode(o:Object):String
{
return new JSONPlusEncoder(o).getString();
}

public static function decode(o:String, strict:Boolean = true):*
{
return new JSONPlusDecoder(o, strict).getValue();
}

}
}

 

package
{
import JSONPlus;
import com.adobe.serialization.json.JSONEncoder;
import flash.utils.getQualifiedClassName;
import flash.utils.describeType;

/**
* Note this implementation depends on monkey patching Adobe’s
* implementation (changing access type to protected)
* – big surprise – yet again a public facing
* API riddled with private methods.
* I wish they would learn to use protected.
*
*/
public class JSONPlusEncoder extends JSONEncoder
{

public function JSONPlusEncoder(value:*)
{
super(value);
}

override protected function objectToString(o:Object):String
{
var classInfo:XML = describeType( o );
if ( classInfo.@name.toString() == “Object” ) return super.objectToString(o);

//strip off the last bracket and insert the fully quallfied class name
var str:String = super.objectToString(o);
str = str.substring(0, str.length – 1);
str += ‘,”‘+ JSONPlus.FQCN_IDENTIFIER +’”:”‘+ getQualifiedClassName(o) +’”}’;

return str;
}
}
}

 

package
{
import JSONPlus;
import JSONDecoder;

import flash.utils.getDefinitionByName;

/**
* Note this implementation depends on monkey patching Adobe’s
* implementation – big surprise – yet again a public facing
* API riddled with private methods.
* I wish they would learn to use protected.
*
*/
public class JSONPlusDecoder extends JSONDecoder
{
private static var map:Object = {};

public function JSONPlusDecoder(value:String, strict:Boolean)
{
super(value, strict);
}

override protected function parseObject():Object
{
var o:Object = super.parseObject();
if (!o.hasOwnProperty(‘fqcn’)) return o;

var className:String = o.fqcn;
var cls:Class = getDefinitionByName(o.fqcn) as Class;

var instance:* = new cls();
for (var key:String in o)
{
if (key !=JSONPlus.FQCN_IDENTIFIER) instance[key] = o[key];
}
return instance;
}
}
}