package org.libspark.common.serialize { import com.adobe.serialization.json.JSON; import flash.utils.ByteArray; import flash.utils.Dictionary; import flash.utils.getDefinitionByName; import org.libspark.common.reflect.InstanceFactory; import org.libspark.common.store.IReadableStore; import org.libspark.common.store.IStorable; public class JSONDeserializer implements IDeserializer, IReadableStore { protected static const OBJECT_KEY:String = '_$OBJ$_'; protected static const CLASS_NAME_KEY:String = '^CNAME'; public function JSONDeserializer() { } private var _sourceString:String; private var _deserializeSuccessful:Boolean; private var _deserializedObject:ISerializable; private var _deserializedObjects:Dictionary; private var _sourceObjects:Object; private var _sourceObject:Object; private var _sourceObjectStack:Array; public function get sourceString():String { return _sourceString; } public function set sourceString(value:String):void { _sourceString = value; } public function get sourceAvailable():Boolean { return sourceString != null; } public function get deserializeSuccessful():Boolean { return _deserializeSuccessful; } protected function setDeserializeSuccessful(value:Boolean):void { _deserializeSuccessful = value; } public function get deserializedObject():ISerializable { return _deserializedObject; } protected function setDeserializedObject(value:ISerializable):void { _deserializedObject = value; } protected function get deserializedObjects():Dictionary { return _deserializedObjects; } protected function set deserializedObjects(value:Dictionary):void { _deserializedObjects = value; } protected function get sourceObjects():Object { return _sourceObjects; } protected function set sourceObjects(value:Object):void { _sourceObjects = value; } protected function get sourceObject():Object { return _sourceObject; } protected function set sourceObject(value:Object):void { _sourceObject = value; } protected function get sourceObjectStack():Array { return _sourceObjectStack; } protected function set sourceObjectStack(value:Array):void { _sourceObjectStack = value; } public function deserialize():void { setDeserializeSuccessful(true); setDeserializedObject(null); var source:Object; try { source = JSON.decode(sourceString); } catch (e:Error) { setDeserializeSuccessful(false); return; } if (source == null || source.objects == null || source.firstKey == null) { setDeserializeSuccessful(false); return; } sourceObjects = source.objects; sourceObject = null; sourceObjectStack = []; deserializedObjects = new Dictionary(); var deserialized:Object = deserializeObject(source.firstKey); if (deserialized == null || deserialized is ISerializable) { setDeserializedObject(deserialized as ISerializable); } else { setDeserializeSuccessful(false); } sourceObjects = null; sourceObject = null; sourceObjectStack = null; deserializedObjects = null; } protected function deserializeObject(value:Object):Object { if (value == null) { return null; } if (value is String) { if ((value as String).substr(0, OBJECT_KEY.length) == OBJECT_KEY) { return deserializeKeyedObject(value as String); } } return value; } protected function deserializeKeyedObject(key:String):Object { if (deserializedObjects[key] != null) { return deserializedObjects[key]; } var source:Object = sourceObjects[key]; if (source == null) { return null; } var deserialized:Object = source; if (CLASS_NAME_KEY in source) { var className:String = source[CLASS_NAME_KEY]; switch (className) { case 'Array': deserialized = deserializeArray(key, source); break; case 'Dictionary': deserialized = deserializeDictionary(key, source); break; default: deserialized = deserializeCustomClass(key, source); break; } } else { deserializedObjects[key] = deserialized; } return deserialized; } protected function deserializeArray(key:String, source:Object):Array { var values:Array = source.values as Array; if (values == null) { return null; } var l:uint = values.length; var obj:Array = new Array(l); deserializedObjects[key] = obj; for (var i:int = 0; i < l; ++i) { obj[i] = deserializeObject(values[i]); } return obj; } protected function deserializeDictionary(key:String, source:Object):Dictionary { var keys:Array = source.keys as Array; var values:Array = source.values as Array; if (keys == null || values == null) { return null; } var l:uint = keys.length; var obj:Dictionary = new Dictionary(); deserializedObjects[key] = obj; for (var i:uint = 0; i < l; ++i) { obj[deserializeObject(keys[i])] = deserializeObject(values[i]); } return obj; } protected function deserializeCustomClass(key:String, source:Object):ISerializable { var className:String = deserializeObject(source[CLASS_NAME_KEY]) as String; var klass:Class; try { klass = getDefinitionByName(className) as Class; } catch (e:Error) { klass = null; } if (klass == null) { return null; } var obj:ISerializable = InstanceFactory.general.makeInstance(klass) as ISerializable; if (obj == null) { return null; } deserializedObjects[key] = obj; sourceObjectStack.push(sourceObject); sourceObject = source; obj.deserialize(this); sourceObject = sourceObjectStack.pop(); return obj; } public function readArray(key:String, defaultValue:Array):Array { if (key in sourceObject) { return deserializeObject(sourceObject[key]) as Array; } return defaultValue; } public function readBoolean(key:String, defaultValue:Boolean):Boolean { if (key in sourceObject) { return sourceObject[key] as Boolean; } return defaultValue; } public function readByteArray(key:String, defaultValue:ByteArray):ByteArray { if (key in sourceObject) { return deserializeObject(sourceObject[key]) as ByteArray; } return defaultValue; } public function readDictionary(key:String, defaultValue:Dictionary):Dictionary { if (key in sourceObject) { return deserializeObject(sourceObject[key]) as Dictionary; } return defaultValue; } public function readInt(key:String, defaultValue:int):int { if (key in sourceObject) { return deserializeObject(sourceObject[key]) as int; } return defaultValue; } public function readNumber(key:String, defaultValue:Number):Number { if (key in sourceObject) { return deserializeObject(sourceObject[key]) as Number; } return defaultValue; } public function readStorable(key:String, defaultValue:IStorable):IStorable { if (key in sourceObject) { return deserializeObject(sourceObject[key]) as IStorable; } return defaultValue; } public function readString(key:String, defaultValue:String):String { if (key in sourceObject) { return deserializeObject(sourceObject[key]) as String; } return defaultValue; } public function readUint(key:String, defaultValue:uint):uint { if (key in sourceObject) { return deserializeObject(sourceObject[key]) as uint; } return defaultValue; } } }