Skip to content

Instantly share code, notes, and snippets.

@cef62
Forked from sinnus/Converter.as
Created July 4, 2012 12:43
Show Gist options
  • Save cef62/3047143 to your computer and use it in GitHub Desktop.
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
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;
}
}
}
@cef62
Copy link
Author

cef62 commented Jul 4, 2012

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 );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment