Mercurial > hg > audiodb
comparison bindings/as3/ext/com/adobe/serialization/json/JSONDecoder.as @ 732:3a0b9700b3d2
* Initial AS3 commit
author | mas01mj |
---|---|
date | Tue, 14 Sep 2010 16:47:10 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
731:65134dd772fc | 732:3a0b9700b3d2 |
---|---|
1 /* | |
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 | |
36 public class JSONDecoder | |
37 { | |
38 | |
39 /** | |
40 * Flag indicating if the parser should be strict about the format | |
41 * of the JSON string it is attempting to decode. | |
42 */ | |
43 private var strict:Boolean; | |
44 | |
45 /** The value that will get parsed from the JSON string */ | |
46 private var value:*; | |
47 | |
48 /** The tokenizer designated to read the JSON string */ | |
49 private var tokenizer:JSONTokenizer; | |
50 | |
51 /** The current token from the tokenizer */ | |
52 private var token:JSONToken; | |
53 | |
54 /** | |
55 * Constructs a new JSONDecoder to parse a JSON string | |
56 * into a native object. | |
57 * | |
58 * @param s The JSON string to be converted | |
59 * into a native object | |
60 * @param strict Flag indicating if the JSON string needs to | |
61 * strictly match the JSON standard or not. | |
62 * @langversion ActionScript 3.0 | |
63 * @playerversion Flash 9.0 | |
64 * @tiptext | |
65 */ | |
66 public function JSONDecoder( s:String, strict:Boolean ) | |
67 { | |
68 this.strict = strict; | |
69 tokenizer = new JSONTokenizer( s, strict ); | |
70 | |
71 nextToken(); | |
72 value = parseValue(); | |
73 | |
74 // Make sure the input stream is empty | |
75 if ( strict && nextToken() != null ) | |
76 { | |
77 tokenizer.parseError( "Unexpected characters left in input stream" ); | |
78 } | |
79 } | |
80 | |
81 /** | |
82 * Gets the internal object that was created by parsing | |
83 * the JSON string passed to the constructor. | |
84 * | |
85 * @return The internal object representation of the JSON | |
86 * string that was passed to the constructor | |
87 * @langversion ActionScript 3.0 | |
88 * @playerversion Flash 9.0 | |
89 * @tiptext | |
90 */ | |
91 public function getValue():* | |
92 { | |
93 return value; | |
94 } | |
95 | |
96 /** | |
97 * Returns the next token from the tokenzier reading | |
98 * the JSON string | |
99 */ | |
100 private function nextToken():JSONToken | |
101 { | |
102 return token = tokenizer.getNextToken(); | |
103 } | |
104 | |
105 /** | |
106 * Attempt to parse an array. | |
107 */ | |
108 private function parseArray():Array | |
109 { | |
110 // create an array internally that we're going to attempt | |
111 // to parse from the tokenizer | |
112 var a:Array = new Array(); | |
113 | |
114 // grab the next token from the tokenizer to move | |
115 // past the opening [ | |
116 nextToken(); | |
117 | |
118 // check to see if we have an empty array | |
119 if ( token.type == JSONTokenType.RIGHT_BRACKET ) | |
120 { | |
121 // we're done reading the array, so return it | |
122 return a; | |
123 } | |
124 // in non-strict mode an empty array is also a comma | |
125 // followed by a right bracket | |
126 else if ( !strict && token.type == JSONTokenType.COMMA ) | |
127 { | |
128 // move past the comma | |
129 nextToken(); | |
130 | |
131 // check to see if we're reached the end of the array | |
132 if ( token.type == JSONTokenType.RIGHT_BRACKET ) | |
133 { | |
134 return a; | |
135 } | |
136 else | |
137 { | |
138 tokenizer.parseError( "Leading commas are not supported. Expecting ']' but found " + token.value ); | |
139 } | |
140 } | |
141 | |
142 // deal with elements of the array, and use an "infinite" | |
143 // loop because we could have any amount of elements | |
144 while ( true ) | |
145 { | |
146 // read in the value and add it to the array | |
147 a.push( parseValue() ); | |
148 | |
149 // after the value there should be a ] or a , | |
150 nextToken(); | |
151 | |
152 if ( token.type == JSONTokenType.RIGHT_BRACKET ) | |
153 { | |
154 // we're done reading the array, so return it | |
155 return a; | |
156 } | |
157 else if ( token.type == JSONTokenType.COMMA ) | |
158 { | |
159 // move past the comma and read another value | |
160 nextToken(); | |
161 | |
162 // Allow arrays to have a comma after the last element | |
163 // if the decoder is not in strict mode | |
164 if ( !strict ) | |
165 { | |
166 // Reached ",]" as the end of the array, so return it | |
167 if ( token.type == JSONTokenType.RIGHT_BRACKET ) | |
168 { | |
169 return a; | |
170 } | |
171 } | |
172 } | |
173 else | |
174 { | |
175 tokenizer.parseError( "Expecting ] or , but found " + token.value ); | |
176 } | |
177 } | |
178 return null; | |
179 } | |
180 | |
181 /** | |
182 * Attempt to parse an object. | |
183 */ | |
184 private function parseObject():Object | |
185 { | |
186 // create the object internally that we're going to | |
187 // attempt to parse from the tokenizer | |
188 var o:Object = new Object(); | |
189 | |
190 // store the string part of an object member so | |
191 // that we can assign it a value in the object | |
192 var key:String | |
193 | |
194 // grab the next token from the tokenizer | |
195 nextToken(); | |
196 | |
197 // check to see if we have an empty object | |
198 if ( token.type == JSONTokenType.RIGHT_BRACE ) | |
199 { | |
200 // we're done reading the object, so return it | |
201 return o; | |
202 } | |
203 // in non-strict mode an empty object is also a comma | |
204 // followed by a right bracket | |
205 else if ( !strict && token.type == JSONTokenType.COMMA ) | |
206 { | |
207 // move past the comma | |
208 nextToken(); | |
209 | |
210 // check to see if we're reached the end of the object | |
211 if ( token.type == JSONTokenType.RIGHT_BRACE ) | |
212 { | |
213 return o; | |
214 } | |
215 else | |
216 { | |
217 tokenizer.parseError( "Leading commas are not supported. Expecting '}' but found " + token.value ); | |
218 } | |
219 } | |
220 | |
221 // deal with members of the object, and use an "infinite" | |
222 // loop because we could have any amount of members | |
223 while ( true ) | |
224 { | |
225 if ( token.type == JSONTokenType.STRING ) | |
226 { | |
227 // the string value we read is the key for the object | |
228 key = String( token.value ); | |
229 | |
230 // move past the string to see what's next | |
231 nextToken(); | |
232 | |
233 // after the string there should be a : | |
234 if ( token.type == JSONTokenType.COLON ) | |
235 { | |
236 // move past the : and read/assign a value for the key | |
237 nextToken(); | |
238 o[key] = parseValue(); | |
239 | |
240 // move past the value to see what's next | |
241 nextToken(); | |
242 | |
243 // after the value there's either a } or a , | |
244 if ( token.type == JSONTokenType.RIGHT_BRACE ) | |
245 { | |
246 // we're done reading the object, so return it | |
247 return o; | |
248 } | |
249 else if ( token.type == JSONTokenType.COMMA ) | |
250 { | |
251 // skip past the comma and read another member | |
252 nextToken(); | |
253 | |
254 // Allow objects to have a comma after the last member | |
255 // if the decoder is not in strict mode | |
256 if ( !strict ) | |
257 { | |
258 // Reached ",}" as the end of the object, so return it | |
259 if ( token.type == JSONTokenType.RIGHT_BRACE ) | |
260 { | |
261 return o; | |
262 } | |
263 } | |
264 } | |
265 else | |
266 { | |
267 tokenizer.parseError( "Expecting } or , but found " + token.value ); | |
268 } | |
269 } | |
270 else | |
271 { | |
272 tokenizer.parseError( "Expecting : but found " + token.value ); | |
273 } | |
274 } | |
275 else | |
276 { | |
277 tokenizer.parseError( "Expecting string but found " + token.value ); | |
278 } | |
279 } | |
280 return null; | |
281 } | |
282 | |
283 /** | |
284 * Attempt to parse a value | |
285 */ | |
286 private function parseValue():Object | |
287 { | |
288 // Catch errors when the input stream ends abruptly | |
289 if ( token == null ) | |
290 { | |
291 tokenizer.parseError( "Unexpected end of input" ); | |
292 } | |
293 | |
294 switch ( token.type ) | |
295 { | |
296 case JSONTokenType.LEFT_BRACE: | |
297 return parseObject(); | |
298 | |
299 case JSONTokenType.LEFT_BRACKET: | |
300 return parseArray(); | |
301 | |
302 case JSONTokenType.STRING: | |
303 case JSONTokenType.NUMBER: | |
304 case JSONTokenType.TRUE: | |
305 case JSONTokenType.FALSE: | |
306 case JSONTokenType.NULL: | |
307 return token.value; | |
308 | |
309 case JSONTokenType.NAN: | |
310 if ( !strict ) | |
311 { | |
312 return token.value; | |
313 } | |
314 else | |
315 { | |
316 tokenizer.parseError( "Unexpected " + token.value ); | |
317 } | |
318 | |
319 default: | |
320 tokenizer.parseError( "Unexpected " + token.value ); | |
321 | |
322 } | |
323 | |
324 return null; | |
325 } | |
326 } | |
327 } |