Using JSON.stringify() on an ActionScript XML class does not return a usable result. The XMLList class does not define toJSON() at all; in this case, JSON.stringify() returns the string resulting from a standard traversal of the object. How can I override this default behavior to customize how my XML or XMLList maps to JSON?
Way #1: Convert XML object to Object and pass it into JSON.stringify method. Way #2 (thanks Richard): Override toJSON method (for XML) or add toJSON method (for XMLList) through prototype.
Way #1: Convert XML object to Object and pass it into JSON.stringify method.
Something like:
//Converter
package
{
import flash.xml.XMLDocument;
import flash.xml.XMLNode;
import flash.xml.XMLNodeType;
public class XMLToObjectConverter
{
//---------------------------------------------------------------------
//
// public methods
//
//---------------------------------------------------------------------
public static function converXMLToObject(xml:XML):Object
{
var xmlDocument:XMLDocument = new XMLDocument(xml.toXMLString());
return _getObjectFromXMLNode(xmlDocument.firstChild);
}
public static function converXMLListToObject(xmlList:XMLList):Object
{
var result:Array = [];
for each(var xml:XML in xmlList)
{
result.push(converXMLToObject(xml));
}
return result;
}
//---------------------------------------------------------------------
//
// private methods
//
//---------------------------------------------------------------------
private static function _getObjectFromXMLNode(node:XMLNode):Object
{
var result:Object = { };
switch(node.nodeType)
{
case XMLNodeType.ELEMENT_NODE:
{
//node name
result['name'] = node.nodeName;
result['type'] = 'element';
//node attributes
var attributes:Object = node.attributes;
var isNodeHaveAttributes:Boolean;
for (var attr:* in attributes)
{
isNodeHaveAttributes = true;
break;
}
if (isNodeHaveAttributes)
{
result['attributes'] = attributes;
}
//node children
if (node.hasChildNodes())
{
var children:Array = [];
var i:uint;
var count:uint = node.childNodes.length;
for (i; i < count; i++)
{
var childNode:XMLNode = node.childNodes[i];
var childNodeObj:Object = _getObjectFromXMLNode(childNode);
if (childNodeObj)
{
children.push(childNodeObj);
}
}
result['children'] = children;
}
break;
}
case XMLNodeType.TEXT_NODE:
{
//filter empty string text nodes
var nodeValue:String = node.nodeValue;
nodeValue = nodeValue.split('\t').join('').split(' ').join('');
nodeValue = nodeValue.split('\n').join('').split('\r').join('');
if (!nodeValue)
{
return null;
}
result['type'] = 'text';
result['text'] = nodeValue;
break;
}
default:
{
return null;
}
}
return result;
}
}
}
//Usage
var xml:XML =
<data>
<item part="1">
<item data="itemData1">Some text 1</item>
<item data="itemData2">Some text 2</item>
</item>
<item part="2">
<item data="itemData4">
<subitem>Some subitem text 1</subitem>
</item>
<item data="itemData5">Some text 3</item>
</item>
</data>
var obj1:Object = XMLToObjectConverter.converXMLToObject(xml);
var list:XMLList = xml.elements('item');
var obj2:Object = XMLToObjectConverter.converXMLListToObject(list);
trace(JSON.stringify(obj1));
trace(JSON.stringify(obj2));
----------------------------------------------------
Way #2 (thanks Richard):
Override toJSON method (for XML) or add toJSON method (for XMLList) through prototype.
BETA ActionScript® 3.0 Reference for toJSON() method of XML class says:
"Provides an overridable method for customizing the JSON encoding of values in an XML object.".
Here is the reference page: http://goo.gl/4r6nv.
XML.prototype.toJSON = function():*
{
var result:String = '';
result += 'Overrided toJSON result for XML:\n';
//here this is reference to current XML object
result += this.toXMLString();
return result;
}
XMLList.prototype.toJSON = function():*
{
var result:String = '';
result += 'Overrided toJSON result for XMLList:\n';
//here this is reference to current XMLList object
result += this.toXMLString();
return result;
}
var xml:XML =
<data>
<item part="1">
<item data="itemData1">Some text 1</item>
<item data="itemData2">Some text 2</item>
</item>
<item part="2">
<item data="itemData4">
<subitem>Some subitem text 1</subitem>
</item>
<item data="itemData5">Some text 3</item>
</item>
</data>
trace(JSON.stringify(xml));
trace(JSON.stringify(xml.item));
+