2 Adobe Systems Incorporated(r) Source Code License Agreement
3 Copyright(c) 2005 Adobe Systems Incorporated. All rights reserved.
5 Please read this Source Code License Agreement carefully before using
8 Adobe Systems Incorporated grants to you a perpetual, worldwide, non-exclusive,
9 no-charge, royalty-free, irrevocable copyright license, to reproduce,
10 prepare derivative works of, publicly display, publicly perform, and
11 distribute this source code and such derivative works in source or
12 object code form without any attribution requirements.
14 The name "Adobe Systems Incorporated" must not be used to endorse or promote products
15 derived from the source code without prior written permission.
17 You agree to indemnify, hold harmless and defend Adobe Systems Incorporated from and
18 against any loss, damage, claims or lawsuits, including attorney's
19 fees that arise or result from your use or distribution of the source
22 THIS SOURCE CODE IS PROVIDED "AS IS" AND "WITH ALL FAULTS", WITHOUT
23 ANY TECHNICAL SUPPORT OR ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
24 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ALSO, THERE IS NO WARRANTY OF
26 NON-INFRINGEMENT, TITLE OR QUIET ENJOYMENT. IN NO EVENT SHALL MACROMEDIA
27 OR ITS SUPPLIERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
30 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOURCE CODE, EVEN IF
33 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 package com.adobe.serialization.json {
41 public class JSONEncoder {
43 /** The string that is going to represent the object we're encoding */
44 private var jsonString:String;
47 * Creates a new JSONEncoder.
49 * @param o The object to encode as a JSON string
50 * @langversion ActionScript 3.0
51 * @playerversion Flash 8.5
54 public function JSONEncoder( o:Object ) {
55 jsonString = convertToString( o );
60 * Gets the JSON string from the encoder.
62 * @return The JSON string representation of the object
63 * that was passed to the constructor
64 * @langversion ActionScript 3.0
65 * @playerversion Flash 8.5
68 public function getString():String {
73 * Converts a value to it's JSON string equivalent.
75 * @param value The value to convert. Could be any
76 * type (object, number, array, etc)
78 private function convertToString( value:Object ):String {
80 // determine what value is and convert it based on it's type
81 if ( value is String ) {
83 // escape the string so it's formatted correctly
84 return escapeString( value as String );
86 } else if ( value is Number ) {
88 // only encode numbers that finate
89 return isFinite( value as Number) ? value.toString() : "null";
91 } else if ( value is Boolean ) {
93 // convert boolean to string easily
94 return value ? "true" : "false";
96 } else if ( value is Array ) {
98 // call the helper method to convert an array
99 return arrayToString( value as Array );
101 } else if ( value is Object && value != null ) {
103 // call the helper method to convert an object
104 return objectToString( value );
110 * Escapes a string accoding to the JSON specification.
112 * @param str The string to be escaped
113 * @return The string with escaped special characters
114 * according to the JSON specification
116 private function escapeString( str:String ):String {
117 // create a string to store the string's jsonstring value
119 // current character in the string we're processing
121 // store the length in a local variable to reduce lookups
122 var len:Number = str.length;
124 // loop over all of the characters in the string
125 for ( var i:int = 0; i < len; i++ ) {
127 // examine the character to determine if we have to escape it
128 ch = str.charAt( i );
131 case '"': // quotation mark
135 //case '/': // solidus
139 case '\\': // reverse solidus
147 case '\f': // form feed
151 case '\n': // newline
155 case '\r': // carriage return
159 case '\t': // horizontal tab
163 default: // everything else
165 // check for a control character and escape as unicode
167 // get the hex digit(s) of the character (either 1 or 2 digits)
168 var hexCode:String = ch.charCodeAt( 0 ).toString( 16 );
170 // ensure that there are 4 digits by adjusting
171 // the # of zeros accordingly.
172 var zeroPad:String = hexCode.length == 2 ? "00" : "000";
174 // create the unicode escape sequence with 4 hex digits
175 s += "\\u" + zeroPad + hexCode;
178 // no need to do any special encoding, just pass-through
186 return "\"" + s + "\"";
190 * Converts an array to it's JSON string equivalent
192 * @param a The array to convert
193 * @return The JSON string representation of <code>a</code>
195 private function arrayToString( a:Array ):String {
196 // create a string to store the array's jsonstring value
199 // loop over the elements in the array and add their converted
200 // values to the string
201 for ( var i:int = 0; i < a.length; i++ ) {
202 // when the length is 0 we're adding the first element so
203 // no comma is necessary
204 if ( s.length > 0 ) {
205 // we've already added an element, so add the comma separator
209 // convert the value to a string
210 s += convertToString( a[i] );
213 // KNOWN ISSUE: In ActionScript, Arrays can also be associative
214 // objects and you can put anything in them, ie:
215 // myArray["foo"] = "bar";
217 // These properties aren't picked up in the for loop above because
218 // the properties don't correspond to indexes. However, we're
219 // sort of out luck because the JSON specification doesn't allow
220 // these types of array properties.
222 // So, if the array was also used as an associative object, there
223 // may be some values in the array that don't get properly encoded.
225 // A possible solution is to instead encode the Array as an Object
226 // but then it won't get decoded correctly (and won't be an
229 // close the array and return it's string value
230 return "[" + s + "]";
234 * Converts an object to it's JSON string equivalent
236 * @param o The object to convert
237 * @return The JSON string representation of <code>o</code>
239 private function objectToString( o:Object ):String {
241 // create a string to store the object's jsonstring value
244 // the value of o[key] in the loop below - store this
245 // as a variable so we don't have to keep looking up o[key]
246 // when testing for valid values to convert
249 // loop over the keys in the object and add their converted
250 // values to the string
251 for ( var key:String in o ) {
252 // assign value to a variable for quick lookup
255 // don't add function's to the JSON string
256 if ( value is Function ) {
257 // skip this key and try another
261 // when the length is 0 we're adding the first item so
262 // no comma is necessary
263 if ( s.length > 0 ) {
264 // we've already added an item, so add the comma separator
268 s += escapeString( key ) + ":" + convertToString( value );
271 return "{" + s + "}";