-
-
Save cef62/3047143 to your computer and use it in GitHub Desktop.
An utility class to permit deserialization from JSON strings to As3 Typed Objects. To original implementation by Sinnus, I've added possibilities to define mapping for properties typed as Interfaces. The Mapping can be supplied via registerClassAlias() me
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package | |
{ | |
import flash.net.getClassByAlias; | |
import flash.utils.describeType; | |
import flash.utils.getDefinitionByName; | |
import flash.utils.getQualifiedClassName; | |
import mx.utils.ObjectUtil; | |
public class JSONConverter | |
{ | |
//-------------------------------------- | |
// Private Static Properties | |
//-------------------------------------- | |
static private var _simpleTypes : Array = [ Boolean, Number, String, int, uint ]; | |
static private var _interfacesMapping : Object = {}; | |
//-------------------------------------- | |
// Private Static Functions | |
//-------------------------------------- | |
static private function createData( rawData : Object, clazz : Class ) : * | |
{ | |
var result : Object; | |
var describeTypeXML : XML; | |
var variable : XML; | |
var accessor : XML; | |
var qInterfaceName : String; | |
if( clazz == Object ) | |
return rawData; | |
if( rawData != null ) | |
{ | |
if( _simpleTypes.indexOf( clazz ) > -1 ) | |
return rawData; | |
else | |
{ | |
try | |
{ | |
result = new clazz(); | |
} | |
catch( e : Error ) | |
{ | |
// try to verify if isn't an interface with a known mapping | |
qInterfaceName = getQualifiedClassName( clazz ); | |
clazz = getClassForInterface( qInterfaceName ); | |
// try to verify maping via registerClassAlias method | |
if( clazz == null ) | |
clazz = getClassByAlias( qInterfaceName ); | |
if( clazz != null ) | |
result = new clazz(); | |
} | |
if( clazz != null ) | |
{ | |
describeTypeXML = describeType( clazz ); | |
for each( variable in describeTypeXML..variable ) | |
processVar( variable, rawData, result ); | |
for each( accessor in describeTypeXML..accessor ) | |
{ | |
if( accessor.@access == "readwrite" ) | |
processVar( accessor, rawData, result ); | |
} | |
return result; | |
} | |
} | |
} | |
return null; | |
} | |
static private function populateArray( data : Array, clazz : Class ) : Array | |
{ | |
var result : Array = new Array( data.length ); | |
for( var i : int = 0; i < data.length; i++ ) | |
result[ i ] = createData( data[ i ], clazz ); | |
return result; | |
} | |
static private function processVar( variable : XML, rawData : Object, result : Object ) : void | |
{ | |
if( variable.@type == "Array" ) | |
{ | |
var array : Array = rawData[ variable.@name ]; | |
if( array ) | |
{ | |
var metaType : Class = Object; | |
for each( var metadata : XML in variable..metadata ) | |
{ | |
if( metadata.@name == "ArrayElementType" ) | |
metaType = getDefinitionByName( metadata..arg.@value ) as Class; | |
} | |
result[ variable.@name ] = populateArray( array, metaType ); | |
} | |
} | |
else | |
{ | |
result[ variable.@name ] = createData( rawData[ variable.@name ], | |
getDefinitionByName( variable.@type ) as Class ) | |
} | |
} | |
//-------------------------------------- | |
// Public Static Functions | |
//-------------------------------------- | |
static public function convertData( rawData : Object, clazz : Class ) : * | |
{ | |
if( rawData === null ) | |
return null; | |
if( describeType( rawData ).@name == "Array" ) | |
return populateArray( rawData as Array, clazz ); | |
else | |
return createData( rawData, clazz ); | |
} | |
static public function getClassForInterface( interfaceQualifiedName : String ) : Class | |
{ | |
if( _interfacesMapping.hasOwnProperty( interfaceQualifiedName ) ) | |
return _interfacesMapping[ interfaceQualifiedName ] as Class; | |
else | |
return null; | |
} | |
static public function toRawData( object : * ) : Object | |
{ | |
if( object === null ) | |
return null; | |
for each( var clazz : Class in _simpleTypes ) | |
{ | |
if( object is clazz ) | |
return object; | |
} | |
if( object is Array ) | |
{ | |
var arrayResult : Array = []; | |
for each( var item : Object in object ) | |
arrayResult.push( toRawData( item ) ); | |
return arrayResult; | |
} | |
var result : Object = {}; | |
var classInfo : Object = ObjectUtil.getClassInfo( object ); | |
for each( var p : String in classInfo.properties ) | |
result[ p ] = toRawData( object[ p ] ); | |
return result; | |
} | |
static public function setInterfaceMapping( interfaceClass : Class, concreteClass : Class ) : void | |
{ | |
var interfaceQualifiedName : String = getQualifiedClassName( interfaceClass ); | |
if( interfaceQualifiedName != null ) | |
_interfacesMapping[ interfaceQualifiedName ] = concreteClass; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example to map an interface to a concrete Class with any of the 3 available options:
registerClassAlias() with manual alias
registerClassAlias( "my.application.namespace::MyInterface", MyInterfaceImplementation );
registerClassAlias() via getQualifiedClassName()
registerClassAlias( getQualifiedClassName( MyInterface ), MyInterfaceImplementation );
Manual mapping
JSONConverter.setInterfaceMapping( MyInterface, MyInterfaceImplementation );