/flowplayer/branches/3_1_3_dev/lib/corelib/src/com/adobe/serialization/json/JSONDecoder.as

http://flowplayer-core.googlecode.com/ · ActionScript · 224 lines · 90 code · 34 blank · 100 comment · 27 complexity · 04fd0590aa889b43f17ddb4826e66180 MD5 · raw file

  1. /*
  2. Adobe Systems Incorporated(r) Source Code License Agreement
  3. Copyright(c) 2005 Adobe Systems Incorporated. All rights reserved.
  4. Please read this Source Code License Agreement carefully before using
  5. the source code.
  6. Adobe Systems Incorporated grants to you a perpetual, worldwide, non-exclusive,
  7. no-charge, royalty-free, irrevocable copyright license, to reproduce,
  8. prepare derivative works of, publicly display, publicly perform, and
  9. distribute this source code and such derivative works in source or
  10. object code form without any attribution requirements.
  11. The name "Adobe Systems Incorporated" must not be used to endorse or promote products
  12. derived from the source code without prior written permission.
  13. You agree to indemnify, hold harmless and defend Adobe Systems Incorporated from and
  14. against any loss, damage, claims or lawsuits, including attorney's
  15. fees that arise or result from your use or distribution of the source
  16. code.
  17. THIS SOURCE CODE IS PROVIDED "AS IS" AND "WITH ALL FAULTS", WITHOUT
  18. ANY TECHNICAL SUPPORT OR ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
  19. BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ALSO, THERE IS NO WARRANTY OF
  21. NON-INFRINGEMENT, TITLE OR QUIET ENJOYMENT. IN NO EVENT SHALL MACROMEDIA
  22. OR ITS SUPPLIERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  23. EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  24. PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  25. OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  26. WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  27. OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOURCE CODE, EVEN IF
  28. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. package com.adobe.serialization.json {
  31. public class JSONDecoder {
  32. /** The value that will get parsed from the JSON string */
  33. private var value:*;
  34. /** The tokenizer designated to read the JSON string */
  35. private var tokenizer:JSONTokenizer;
  36. /** The current token from the tokenizer */
  37. private var token:JSONToken;
  38. /**
  39. * Constructs a new JSONDecoder to parse a JSON string
  40. * into a native object.
  41. *
  42. * @param s The JSON string to be converted
  43. * into a native object
  44. * @langversion ActionScript 3.0
  45. * @playerversion Flash 9.0
  46. * @tiptext
  47. */
  48. public function JSONDecoder( s:String ) {
  49. tokenizer = new JSONTokenizer( s );
  50. nextToken();
  51. value = parseValue();
  52. }
  53. /**
  54. * Gets the internal object that was created by parsing
  55. * the JSON string passed to the constructor.
  56. *
  57. * @return The internal object representation of the JSON
  58. * string that was passed to the constructor
  59. * @langversion ActionScript 3.0
  60. * @playerversion Flash 9.0
  61. * @tiptext
  62. */
  63. public function getValue():* {
  64. return value;
  65. }
  66. /**
  67. * Returns the next token from the tokenzier reading
  68. * the JSON string
  69. */
  70. private function nextToken():JSONToken {
  71. return token = tokenizer.getNextToken();
  72. }
  73. /**
  74. * Attempt to parse an array
  75. */
  76. private function parseArray():Array {
  77. // create an array internally that we're going to attempt
  78. // to parse from the tokenizer
  79. var a:Array = new Array();
  80. // grab the next token from the tokenizer to move
  81. // past the opening [
  82. nextToken();
  83. // check to see if we have an empty array
  84. if ( token.type == JSONTokenType.RIGHT_BRACKET ) {
  85. // we're done reading the array, so return it
  86. return a;
  87. }
  88. // deal with elements of the array, and use an "infinite"
  89. // loop because we could have any amount of elements
  90. while ( true ) {
  91. // read in the value and add it to the array
  92. a.push ( parseValue() );
  93. // after the value there should be a ] or a ,
  94. nextToken();
  95. if ( token.type == JSONTokenType.RIGHT_BRACKET ) {
  96. // we're done reading the array, so return it
  97. return a;
  98. } else if ( token.type == JSONTokenType.COMMA ) {
  99. // move past the comma and read another value
  100. nextToken();
  101. } else {
  102. tokenizer.parseError( "Expecting ] or , but found " + token.value );
  103. }
  104. }
  105. return null;
  106. }
  107. /**
  108. * Attempt to parse an object
  109. */
  110. private function parseObject():Object {
  111. // create the object internally that we're going to
  112. // attempt to parse from the tokenizer
  113. var o:Object = new Object();
  114. // store the string part of an object member so
  115. // that we can assign it a value in the object
  116. var key:String
  117. // grab the next token from the tokenizer
  118. nextToken();
  119. // check to see if we have an empty object
  120. if ( token.type == JSONTokenType.RIGHT_BRACE ) {
  121. // we're done reading the object, so return it
  122. return o;
  123. }
  124. // deal with members of the object, and use an "infinite"
  125. // loop because we could have any amount of members
  126. while ( true ) {
  127. if ( token.type == JSONTokenType.STRING ) {
  128. // the string value we read is the key for the object
  129. key = String( token.value );
  130. // move past the string to see what's next
  131. nextToken();
  132. // after the string there should be a :
  133. if ( token.type == JSONTokenType.COLON ) {
  134. // move past the : and read/assign a value for the key
  135. nextToken();
  136. o[key] = parseValue();
  137. // move past the value to see what's next
  138. nextToken();
  139. // after the value there's either a } or a ,
  140. if ( token.type == JSONTokenType.RIGHT_BRACE ) {
  141. // // we're done reading the object, so return it
  142. return o;
  143. } else if ( token.type == JSONTokenType.COMMA ) {
  144. // skip past the comma and read another member
  145. nextToken();
  146. } else {
  147. tokenizer.parseError( "Expecting } or , but found " + token.value );
  148. }
  149. } else {
  150. tokenizer.parseError( "Expecting : but found " + token.value );
  151. }
  152. } else {
  153. tokenizer.parseError( "Expecting string but found " + token.value );
  154. }
  155. }
  156. return null;
  157. }
  158. /**
  159. * Attempt to parse a value
  160. */
  161. private function parseValue():Object
  162. {
  163. // Catch errors when the input stream ends abruptly
  164. if ( token == null )
  165. {
  166. tokenizer.parseError( "Unexpected end of input" );
  167. }
  168. switch ( token.type ) {
  169. case JSONTokenType.LEFT_BRACE:
  170. return parseObject();
  171. case JSONTokenType.LEFT_BRACKET:
  172. return parseArray();
  173. case JSONTokenType.STRING:
  174. case JSONTokenType.NUMBER:
  175. case JSONTokenType.TRUE:
  176. case JSONTokenType.FALSE:
  177. case JSONTokenType.NULL:
  178. return token.value;
  179. default:
  180. tokenizer.parseError( "Unexpected " + token.value );
  181. }
  182. return null;
  183. }
  184. }
  185. }