+++ /dev/null
-/*\r
- Copyright (c) 2008, Adobe Systems Incorporated\r
- All rights reserved.\r
-\r
- Redistribution and use in source and binary forms, with or without \r
- modification, are permitted provided that the following conditions are\r
- met:\r
-\r
- * Redistributions of source code must retain the above copyright notice, \r
- this list of conditions and the following disclaimer.\r
- \r
- * Redistributions in binary form must reproduce the above copyright\r
- notice, this list of conditions and the following disclaimer in the \r
- documentation and/or other materials provided with the distribution.\r
- \r
- * Neither the name of Adobe Systems Incorporated nor the names of its \r
- contributors may be used to endorse or promote products derived from \r
- this software without specific prior written permission.\r
-\r
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS\r
- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r
- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR \r
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
-*/\r
-\r
-package com.adobe.serialization.json \r
-{\r
-\r
- import flash.utils.describeType;\r
-\r
- public class JSONEncoder {\r
- \r
- /** The string that is going to represent the object we're encoding */\r
- private var jsonString:String;\r
- \r
- /**\r
- * Creates a new JSONEncoder.\r
- *\r
- * @param o The object to encode as a JSON string\r
- * @langversion ActionScript 3.0\r
- * @playerversion Flash 9.0\r
- * @tiptext\r
- */\r
- public function JSONEncoder( value:* ) {\r
- jsonString = convertToString( value );\r
- \r
- }\r
- \r
- /**\r
- * Gets the JSON string from the encoder.\r
- *\r
- * @return The JSON string representation of the object\r
- * that was passed to the constructor\r
- * @langversion ActionScript 3.0\r
- * @playerversion Flash 9.0\r
- * @tiptext\r
- */\r
- public function getString():String {\r
- return jsonString;\r
- }\r
- \r
- /**\r
- * Converts a value to it's JSON string equivalent.\r
- *\r
- * @param value The value to convert. Could be any \r
- * type (object, number, array, etc)\r
- */\r
- private function convertToString( value:* ):String {\r
- \r
- // determine what value is and convert it based on it's type\r
- if ( value is String ) {\r
- \r
- // escape the string so it's formatted correctly\r
- return escapeString( value as String );\r
- \r
- } else if ( value is Number ) {\r
- \r
- // only encode numbers that finate\r
- return isFinite( value as Number) ? value.toString() : "null";\r
-\r
- } else if ( value is Boolean ) {\r
- \r
- // convert boolean to string easily\r
- return value ? "true" : "false";\r
-\r
- } else if ( value is Array ) {\r
- \r
- // call the helper method to convert an array\r
- return arrayToString( value as Array );\r
- \r
- } else if ( value is Object && value != null ) {\r
- \r
- // call the helper method to convert an object\r
- return objectToString( value );\r
- }\r
- return "null";\r
- }\r
- \r
- /**\r
- * Escapes a string accoding to the JSON specification.\r
- *\r
- * @param str The string to be escaped\r
- * @return The string with escaped special characters\r
- * according to the JSON specification\r
- */\r
- private function escapeString( str:String ):String {\r
- // create a string to store the string's jsonstring value\r
- var s:String = "";\r
- // current character in the string we're processing\r
- var ch:String;\r
- // store the length in a local variable to reduce lookups\r
- var len:Number = str.length;\r
- \r
- // loop over all of the characters in the string\r
- for ( var i:int = 0; i < len; i++ ) {\r
- \r
- // examine the character to determine if we have to escape it\r
- ch = str.charAt( i );\r
- switch ( ch ) {\r
- \r
- case '"': // quotation mark\r
- s += "\\\"";\r
- break;\r
- \r
- //case '/': // solidus\r
- // s += "\\/";\r
- // break;\r
- \r
- case '\\': // reverse solidus\r
- s += "\\\\";\r
- break;\r
- \r
- case '\b': // bell\r
- s += "\\b";\r
- break;\r
- \r
- case '\f': // form feed\r
- s += "\\f";\r
- break;\r
- \r
- case '\n': // newline\r
- s += "\\n";\r
- break;\r
- \r
- case '\r': // carriage return\r
- s += "\\r";\r
- break;\r
- \r
- case '\t': // horizontal tab\r
- s += "\\t";\r
- break;\r
- \r
- default: // everything else\r
- \r
- // check for a control character and escape as unicode\r
- if ( ch < ' ' ) {\r
- // get the hex digit(s) of the character (either 1 or 2 digits)\r
- var hexCode:String = ch.charCodeAt( 0 ).toString( 16 );\r
- \r
- // ensure that there are 4 digits by adjusting\r
- // the # of zeros accordingly.\r
- var zeroPad:String = hexCode.length == 2 ? "00" : "000";\r
- \r
- // create the unicode escape sequence with 4 hex digits\r
- s += "\\u" + zeroPad + hexCode;\r
- } else {\r
- \r
- // no need to do any special encoding, just pass-through\r
- s += ch;\r
- \r
- }\r
- } // end switch\r
- \r
- } // end for loop\r
- \r
- return "\"" + s + "\"";\r
- }\r
- \r
- /**\r
- * Converts an array to it's JSON string equivalent\r
- *\r
- * @param a The array to convert\r
- * @return The JSON string representation of <code>a</code>\r
- */\r
- private function arrayToString( a:Array ):String {\r
- // create a string to store the array's jsonstring value\r
- var s:String = "";\r
- \r
- // loop over the elements in the array and add their converted\r
- // values to the string\r
- for ( var i:int = 0; i < a.length; i++ ) {\r
- // when the length is 0 we're adding the first element so\r
- // no comma is necessary\r
- if ( s.length > 0 ) {\r
- // we've already added an element, so add the comma separator\r
- s += ","\r
- }\r
- \r
- // convert the value to a string\r
- s += convertToString( a[i] ); \r
- }\r
- \r
- // KNOWN ISSUE: In ActionScript, Arrays can also be associative\r
- // objects and you can put anything in them, ie:\r
- // myArray["foo"] = "bar";\r
- //\r
- // These properties aren't picked up in the for loop above because\r
- // the properties don't correspond to indexes. However, we're\r
- // sort of out luck because the JSON specification doesn't allow\r
- // these types of array properties.\r
- //\r
- // So, if the array was also used as an associative object, there\r
- // may be some values in the array that don't get properly encoded.\r
- //\r
- // A possible solution is to instead encode the Array as an Object\r
- // but then it won't get decoded correctly (and won't be an\r
- // Array instance)\r
- \r
- // close the array and return it's string value\r
- return "[" + s + "]";\r
- }\r
- \r
- /**\r
- * Converts an object to it's JSON string equivalent\r
- *\r
- * @param o The object to convert\r
- * @return The JSON string representation of <code>o</code>\r
- */\r
- private function objectToString( o:Object ):String\r
- {\r
- // create a string to store the object's jsonstring value\r
- var s:String = "";\r
- \r
- // determine if o is a class instance or a plain object\r
- var classInfo:XML = describeType( o );\r
- if ( classInfo.@name.toString() == "Object" )\r
- {\r
- // the value of o[key] in the loop below - store this \r
- // as a variable so we don't have to keep looking up o[key]\r
- // when testing for valid values to convert\r
- var value:Object;\r
- \r
- // loop over the keys in the object and add their converted\r
- // values to the string\r
- for ( var key:String in o )\r
- {\r
- // assign value to a variable for quick lookup\r
- value = o[key];\r
- \r
- // don't add function's to the JSON string\r
- if ( value is Function )\r
- {\r
- // skip this key and try another\r
- continue;\r
- }\r
- \r
- // when the length is 0 we're adding the first item so\r
- // no comma is necessary\r
- if ( s.length > 0 ) {\r
- // we've already added an item, so add the comma separator\r
- s += ","\r
- }\r
- \r
- s += escapeString( key ) + ":" + convertToString( value );\r
- }\r
- }\r
- else // o is a class instance\r
- {\r
- // Loop over all of the variables and accessors in the class and \r
- // serialize them along with their values.\r
- for each ( var v:XML in classInfo..*.( name() == "variable" || name() == "accessor" ) )\r
- {\r
- // When the length is 0 we're adding the first item so\r
- // no comma is necessary\r
- if ( s.length > 0 ) {\r
- // We've already added an item, so add the comma separator\r
- s += ","\r
- }\r
- \r
- s += escapeString( v.@name.toString() ) + ":" \r
- + convertToString( o[ v.@name ] );\r
- }\r
- \r
- }\r
- \r
- return "{" + s + "}";\r
- }\r
-\r
- \r
- }\r
- \r
-}\r