Monday, May 2, 2011

Simple JSON parser

I have written a simple json parser in actionscript. i re-create a wheel because the one in as3corelib is too complicated for me. this is pretty straight forward, it does single pass parsing, convert JSON text into ActionScript Object. currently it supported string, object and array only. i think it is good enough for configuration purposes. so enjoy :)

/**
* Simple JSON parser. this parser does a single pass translation of JSON to
* Actionscript string, array and object. no int and float support yet and no error checking
* as well. but this parser does support nested object and array
* @param content JSON text
* @param stack parser
* @param parent Parent Object or Array depends on context
* @return Object Actionscript object that represent the JSON (content)
*/
private function parse(content:String, stack:Vector., parent:Object):Object {
var ret:Object;
var curr:uint = stack[CFG_POS];
var type:String = content.charAt(curr);
++curr;
stack[CFG_POS] = curr;
switch(type) {
case OPEN_BRACKET_OBJECT:
// push the new stack
stack.unshift(TYPE_OBJECT);
stack.unshift(PART_KEY);
stack.unshift(curr);
ret = new Object;
while(stack[CFG_TYPE] == TYPE_OBJECT){
ret = parse(content, stack, ret);
}
// pop the old stack
curr = stack.shift();
stack.shift();
stack.shift();
stack[CFG_POS] = curr;
break;
case CLOSE_BRACKET_OBJECT:
stack[CFG_TYPE] = NA; // stop the object's while loop
ret = parent;
break;
case OPEN_BRACKET_ARRAY:
// push the new stack
stack.unshift(TYPE_ARRAY);
stack.unshift(PART_VALUE);
stack.unshift(curr);
ret = new Array;
while(stack[CFG_TYPE] == TYPE_ARRAY){
ret.push(parse(content, stack, ret));
}
ret.pop(); // pop out the unwanted last null set by CLOSE_BRACKET_ARRAY
// pop the old stack
curr = stack.shift();
stack.shift();
stack.shift();
stack[CFG_POS] = curr;
break;
case CLOSE_BRACKET_ARRAY:
stack[CFG_TYPE] = NA; // stop the array's while loop
ret = null;
break;
case BRACKET_ITEM:
stack[CFG_POS] = content.indexOf(BRACKET_ITEM, curr) + 1;
if (stack[CFG_PART] == PART_KEY){
parent[content.substring(curr, stack[CFG_POS]-1)] = parse(content, stack, parent);
ret = parent;
}else{
ret = content.substring(curr, stack[CFG_POS]-1);
}
break;
case SEPARATOR_KEY_VALUE:
stack[CFG_PART] = PART_VALUE;
ret = parse(content, stack, parent);
break;
case SEPARATOR_STATEMENT:
if (stack[CFG_TYPE] == TYPE_OBJECT)
stack[CFG_PART] = PART_KEY;
else
stack[CFG_PART] = PART_VALUE;
ret = parse(content, stack, parent);
break;
}
return ret;
}

No comments: