colonymech / docs / www / colonyscout / internal / includes / uploadify / com / adobe / serialization / json / JSONDecoder.as @ f59acf11
History | View | Annotate | Download (6.41 KB)
1 | f59acf11 | Dan Shope | /* |
---|---|---|---|
2 | Copyright (c) 2008, Adobe Systems Incorporated |
||
3 | All rights reserved. |
||
4 | |||
5 | Redistribution and use in source and binary forms, with or without |
||
6 | modification, are permitted provided that the following conditions are |
||
7 | met: |
||
8 | |||
9 | * Redistributions of source code must retain the above copyright notice, |
||
10 | this list of conditions and the following disclaimer. |
||
11 | |||
12 | * Redistributions in binary form must reproduce the above copyright |
||
13 | notice, this list of conditions and the following disclaimer in the |
||
14 | documentation and/or other materials provided with the distribution. |
||
15 | |||
16 | * Neither the name of Adobe Systems Incorporated nor the names of its |
||
17 | contributors may be used to endorse or promote products derived from |
||
18 | this software without specific prior written permission. |
||
19 | |||
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
||
21 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
||
22 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||
23 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||
24 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||
25 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||
26 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||
27 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||
28 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||
29 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||
30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
31 | */ |
||
32 | |||
33 | package com.adobe.serialization.json { |
||
34 | |||
35 | public class JSONDecoder { |
||
36 | |||
37 | /** The value that will get parsed from the JSON string */ |
||
38 | private var value:*; |
||
39 | |||
40 | /** The tokenizer designated to read the JSON string */ |
||
41 | private var tokenizer:JSONTokenizer; |
||
42 | |||
43 | /** The current token from the tokenizer */ |
||
44 | private var token:JSONToken; |
||
45 | |||
46 | /** |
||
47 | * Constructs a new JSONDecoder to parse a JSON string |
||
48 | * into a native object. |
||
49 | * |
||
50 | * @param s The JSON string to be converted |
||
51 | * into a native object |
||
52 | * @langversion ActionScript 3.0 |
||
53 | * @playerversion Flash 9.0 |
||
54 | * @tiptext |
||
55 | */ |
||
56 | public function JSONDecoder( s:String ) { |
||
57 | |||
58 | tokenizer = new JSONTokenizer( s ); |
||
59 | |||
60 | nextToken(); |
||
61 | value = parseValue(); |
||
62 | } |
||
63 | |||
64 | /** |
||
65 | * Gets the internal object that was created by parsing |
||
66 | * the JSON string passed to the constructor. |
||
67 | * |
||
68 | * @return The internal object representation of the JSON |
||
69 | * string that was passed to the constructor |
||
70 | * @langversion ActionScript 3.0 |
||
71 | * @playerversion Flash 9.0 |
||
72 | * @tiptext |
||
73 | */ |
||
74 | public function getValue():* { |
||
75 | return value; |
||
76 | } |
||
77 | |||
78 | /** |
||
79 | * Returns the next token from the tokenzier reading |
||
80 | * the JSON string |
||
81 | */ |
||
82 | private function nextToken():JSONToken { |
||
83 | return token = tokenizer.getNextToken(); |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * Attempt to parse an array |
||
88 | */ |
||
89 | private function parseArray():Array { |
||
90 | // create an array internally that we're going to attempt |
||
91 | // to parse from the tokenizer |
||
92 | var a:Array = new Array(); |
||
93 | |||
94 | // grab the next token from the tokenizer to move |
||
95 | // past the opening [ |
||
96 | nextToken(); |
||
97 | |||
98 | // check to see if we have an empty array |
||
99 | if ( token.type == JSONTokenType.RIGHT_BRACKET ) { |
||
100 | // we're done reading the array, so return it |
||
101 | return a; |
||
102 | } |
||
103 | |||
104 | // deal with elements of the array, and use an "infinite" |
||
105 | // loop because we could have any amount of elements |
||
106 | while ( true ) { |
||
107 | // read in the value and add it to the array |
||
108 | a.push ( parseValue() ); |
||
109 | |||
110 | // after the value there should be a ] or a , |
||
111 | nextToken(); |
||
112 | |||
113 | if ( token.type == JSONTokenType.RIGHT_BRACKET ) { |
||
114 | // we're done reading the array, so return it |
||
115 | return a; |
||
116 | } else if ( token.type == JSONTokenType.COMMA ) { |
||
117 | // move past the comma and read another value |
||
118 | nextToken(); |
||
119 | } else { |
||
120 | tokenizer.parseError( "Expecting ] or , but found " + token.value ); |
||
121 | } |
||
122 | } |
||
123 | return null; |
||
124 | } |
||
125 | |||
126 | /** |
||
127 | * Attempt to parse an object |
||
128 | */ |
||
129 | private function parseObject():Object { |
||
130 | // create the object internally that we're going to |
||
131 | // attempt to parse from the tokenizer |
||
132 | var o:Object = new Object(); |
||
133 | |||
134 | // store the string part of an object member so |
||
135 | // that we can assign it a value in the object |
||
136 | var key:String |
||
137 | |||
138 | // grab the next token from the tokenizer |
||
139 | nextToken(); |
||
140 | |||
141 | // check to see if we have an empty object |
||
142 | if ( token.type == JSONTokenType.RIGHT_BRACE ) { |
||
143 | // we're done reading the object, so return it |
||
144 | return o; |
||
145 | } |
||
146 | |||
147 | // deal with members of the object, and use an "infinite" |
||
148 | // loop because we could have any amount of members |
||
149 | while ( true ) { |
||
150 | |||
151 | if ( token.type == JSONTokenType.STRING ) { |
||
152 | // the string value we read is the key for the object |
||
153 | key = String( token.value ); |
||
154 | |||
155 | // move past the string to see what's next |
||
156 | nextToken(); |
||
157 | |||
158 | // after the string there should be a : |
||
159 | if ( token.type == JSONTokenType.COLON ) { |
||
160 | |||
161 | // move past the : and read/assign a value for the key |
||
162 | nextToken(); |
||
163 | o[key] = parseValue(); |
||
164 | |||
165 | // move past the value to see what's next |
||
166 | nextToken(); |
||
167 | |||
168 | // after the value there's either a } or a , |
||
169 | if ( token.type == JSONTokenType.RIGHT_BRACE ) { |
||
170 | // // we're done reading the object, so return it |
||
171 | return o; |
||
172 | |||
173 | } else if ( token.type == JSONTokenType.COMMA ) { |
||
174 | // skip past the comma and read another member |
||
175 | nextToken(); |
||
176 | } else { |
||
177 | tokenizer.parseError( "Expecting } or , but found " + token.value ); |
||
178 | } |
||
179 | } else { |
||
180 | tokenizer.parseError( "Expecting : but found " + token.value ); |
||
181 | } |
||
182 | } else { |
||
183 | tokenizer.parseError( "Expecting string but found " + token.value ); |
||
184 | } |
||
185 | } |
||
186 | return null; |
||
187 | } |
||
188 | |||
189 | /** |
||
190 | * Attempt to parse a value |
||
191 | */ |
||
192 | private function parseValue():Object |
||
193 | { |
||
194 | // Catch errors when the input stream ends abruptly |
||
195 | if ( token == null ) |
||
196 | { |
||
197 | tokenizer.parseError( "Unexpected end of input" ); |
||
198 | } |
||
199 | |||
200 | switch ( token.type ) { |
||
201 | case JSONTokenType.LEFT_BRACE: |
||
202 | return parseObject(); |
||
203 | |||
204 | case JSONTokenType.LEFT_BRACKET: |
||
205 | return parseArray(); |
||
206 | |||
207 | case JSONTokenType.STRING: |
||
208 | case JSONTokenType.NUMBER: |
||
209 | case JSONTokenType.TRUE: |
||
210 | case JSONTokenType.FALSE: |
||
211 | case JSONTokenType.NULL: |
||
212 | return token.value; |
||
213 | |||
214 | default: |
||
215 | tokenizer.parseError( "Unexpected " + token.value ); |
||
216 | |||
217 | } |
||
218 | return null; |
||
219 | } |
||
220 | } |
||
221 | } |