package org.libspark.common.serialize { import com.adobe.serialization.json.JSON; import flash.utils.ByteArray; import flash.utils.Dictionary; import flash.utils.getQualifiedClassName; import org.libspark.common.store.IStorable; import org.libspark.common.store.IWritableStore; public class JSONSerializer implements ISerializer, IWritableStore { protected static const OBJECT_KEY:String = '_$OBJ$_'; protected static const CLASS_NAME_KEY:String = '^CNAME'; public function JSONSerializer() { } private var _serializedString:String; private var _serializedObject:Object; private var _serializedObjectStack:Array; private var _serializedObjects:Object; private var _serializedObjectKeys:Dictionary; private var _numSerializedObjects:uint; public function get serializeSuccessful():Boolean { return serializedString != null; } public function get serializedString():String { return _serializedString; } protected function setSerializedString(value:String):void { _serializedString = value; } protected function get serializedObject():Object { return _serializedObject; } protected function set serializedObject(value:Object):void { _serializedObject = value; } protected function get serializedObjectStack():Array { return _serializedObjectStack; } protected function set serializedObjectStack(value:Array):void { _serializedObjectStack = value; } protected function get serializedObjects():Object { return _serializedObjects; } protected function set serializedObjects(value:Object):void { _serializedObjects = value; } protected function get serializedObjectKeys():Dictionary { return _serializedObjectKeys; } protected function set serializedObjectKeys(value:Dictionary):void { _serializedObjectKeys = value; } protected function get numSerializedObjects():uint { return _numSerializedObjects; } protected function set numSerializedObjects(value:uint):void { _numSerializedObjects = value; } protected function get serializedObjectKey():String { return OBJECT_KEY + numSerializedObjects; } public function serialize(obj:ISerializable):void { setSerializedString(null); serializedObject = null; serializedObjectStack = []; serializedObjects = new Object(); serializedObjectKeys = new Dictionary(); numSerializedObjects = 0; var firstKey:String = serializeSerializable(obj); var jsonString:String; try { jsonString = JSON.encode({ objects: serializedObjects, firstKey: firstKey }); } catch (e:Error) { jsonString = null; } setSerializedString(jsonString); serializedObject = null; serializedObjectStack = null; serializedObjects = null; serializedObjectKeys = null; } protected function serializeSerializable(obj:ISerializable):String { if (serializedObjectKeys[obj] != null) { return serializedObjectKeys[obj] as String; } var key:String = serializedObjectKey; numSerializedObjects = numSerializedObjects + 1; serializedObjectKeys[obj] = key; if (obj != null) { serializedObjectStack.push(serializedObject); serializedObject = new Object(); serializedObject[CLASS_NAME_KEY] = serializeObject(getQualifiedClassName(obj)); obj.serialize(this); serializedObjects[key] = serializedObject; serializedObject = serializedObjectStack.pop(); } else { serializedObjects[key] = null; } return key; } protected function serializeArray(obj:Array):String { if (serializedObjectKeys[obj] != null) { return serializedObjectKeys[obj] as String; } var key:String = serializedObjectKey; numSerializedObjects = numSerializedObjects + 1; serializedObjectKeys[obj] = key; if (obj != null) { serializedObjectStack.push(serializedObject); serializedObject = new Object(); serializedObject[CLASS_NAME_KEY] = "Array"; var values:Array = []; for (var i:uint = 0, l:uint = obj.length; i < l; ++i) { values.push(serializeObject(obj[i])); } serializedObject["values"] = values; serializedObjects[key] = serializedObject; serializedObject = serializedObjectStack.pop(); } else { serializedObjects[key] = null; } return key; } protected function serializeByteArray(obj:ByteArray):String { return null; } protected function serializeDictionary(obj:Dictionary):String { if (serializedObjectKeys[obj] != null) { return serializedObjectKeys[obj] as String; } var key:String = serializedObjectKey; numSerializedObjects = numSerializedObjects + 1; serializedObjectKeys[obj] = key; if (obj != null) { serializedObjectStack.push(serializedObject); serializedObject = new Object(); serializedObject[CLASS_NAME_KEY] = "Dictionary"; var keys:Array = []; var values:Array = []; for (var objKey:* in obj) { keys.push(serializeObject(objKey)); values.push(serializeObject(obj[objKey])); } serializedObject['keys'] = keys; serializedObject['values'] = values; serializedObjects[key] = serializedObject; serializedObject = serializedObjectStack.pop(); } else { serializedObjects[key] = null; } return key; } protected function serializeObject(obj:Object):String { if (serializedObjectKeys[obj] != null) { return serializedObjectKeys[obj] as String; } if (obj is ISerializable) { return serializeSerializable(obj as ISerializable); } if (obj is Array) { return serializeArray(obj as Array); } if (obj is ByteArray) { return serializeByteArray(obj as ByteArray); } if (obj is Dictionary) { return serializeDictionary(obj as Dictionary); } var key:String = serializedObjectKey; numSerializedObjects = numSerializedObjects + 1; serializedObjectKeys[obj] = key; serializedObjects[key] = obj; return key; } public function writeArray(key:String, value:Array):void { serializedObject[key] = serializeArray(value); } public function writeBoolean(key:String, value:Boolean):void { serializedObject[key] = value; } public function writeByteArray(key:String, value:ByteArray):void { serializedObject[key] = serializeByteArray(value); } public function writeDictionary(key:String, value:Dictionary):void { serializedObject[key] = serializeDictionary(value); } public function writeInt(key:String, value:int):void { serializedObject[key] = value; } public function writeNumber(key:String, value:Number):void { serializedObject[key] = value; } public function writeStorable(key:String, value:IStorable):void { if (value is ISerializable) { serializedObject[key] = serializeSerializable(value as ISerializable); } } public function writeString(key:String, value:String):void { serializedObject[key] = value; } public function writeUint(key:String, value:uint):void { serializedObject[key] = value; } } }