-
var str:String = '{numA:100, numB:100, stringA:"hi there", object:{red:155, green:155, blue: 255}, array1D:[1, 2, 3, 4, 5, "six"], array2D:[[1,0,0], [0,1,0], [0,0,"z"]], color:0xFF0000}'
-
-
var obj:Object = toObject(str);//, true); // comment the "true" in for some debug info
-
-
// acess every value in the object for testing purposes
-
trace(obj.numA);
-
trace(obj.numB);
-
trace(obj.stringA);
-
trace(obj.object.red, obj.object.green, obj.object.blue);
-
trace(obj.array1D +" testing access: " + obj.array1D[3]);
-
trace(obj.array2D + " testing access: " + obj.array2D[1] + " - " + obj.array2D[2][2]);
-
trace(obj.color);
-
-
/*outputs:
-
100
-
100
-
hi there
-
155 155 255
-
1,2,3,4,5,six testing access: 4
-
1,0,0,0,1,0,0,0,z testing access: 0,1,0 - z
-
16711680
-
*/
-
-
function toObject(str:String, debug:Boolean=false):Object{
-
var cmds:Array = new Array();
-
var stack:String = "";
-
// skip first {
-
str = str.replace(/^\s+\{|^\{/, "");
-
var obj:Object = new Object();
-
for (var i:int = 0; i<str.length; i++){
-
var char:String = str.charAt(i);
-
if (char == ":"){
-
cmds.push(["name:", stack])
-
stack = "";
-
char = "";
-
}else
-
if (char == "," || char == "}"){
-
if (stack != ""){
-
cmds.push(["value:", stack]);
-
}
-
stack = "";
-
char = "";
-
}else
-
if (char == '"'){
-
stack = '"';
-
for (j = i + 1; j <str.length; j++){
-
char = str.charAt(j);
-
stack+=char;
-
i++;
-
if (char == '"'){
-
break;
-
}
-
}
-
cmds.push(["value:", stack]);
-
stack = "";
-
char = "";
-
}else
-
if (char == "{"){
-
cmds.push(["object:", stack]);
-
for (var j:int = i; j <str.length; j++){
-
char = str.charAt(j);
-
stack+=char;
-
i++;
-
if (char == "}"){
-
break;
-
}
-
}
-
cmds.push(["value:", stack]);
-
stack = "";
-
char = "";
-
}else
-
if (char == "["){
-
cmds.push(["array:", stack]);
-
stack = "";
-
char = "";
-
}else if (char == "]"){
-
if (stack != ""){
-
cmds.push(["value:", stack]);
-
}
-
stack = "";
-
char = "";
-
i++;
-
}
-
stack += char;
-
}
-
// show some debug info
-
if (debug){
-
for (i = 0; i<cmds.length; i++) trace(cmds[i]);
-
}
-
// build the object
-
var prop:String;
-
var arrayMode:Boolean = false;
-
var nest:int = 0;
-
for (i = 0; i<cmds.length; i++){
-
if (cmds[i][0] == "name:"){
-
prop = cmds[i][1].replace(/\s/g, "");
-
arrayMode = false;
-
nest = 0;
-
}else if (cmds[i][0] == "value:"){
-
if (arrayMode == false){
-
obj[prop] = valueType(cmds[i][1]);
-
}else{
-
// populate array
-
if (nest == 1){
-
obj[prop].push(valueType(cmds[i][1]))
-
}else{
-
obj[prop][nest - 2].push(valueType(cmds[i][1]))
-
}
-
}
-
}else if (cmds[i][0] == "object:"){
-
i++;
-
obj[prop] = toObject(cmds[i][1], debug);
-
}else if (cmds[i][0] == "array:"){
-
arrayMode = true;
-
nest++;
-
if (nest == 1){
-
// create array
-
obj[prop] = new Array()
-
}else{
-
// nested array
-
obj[prop].push(new Array());
-
}
-
}
-
}
-
return obj;
-
}
-
-
function valueType(val:*):* {
-
if (isNaN(Number(val))) {
-
// remove leading and trailing white
-
// remove "" around strings
-
val = val.replace(/^s+|s+$/g,"").replace(/^"|"$/g,"");
-
// see if it's a boolean
-
if (val == "true"){
-
val = true;
-
}else if (val == "false"){
-
val = false
-
}
-
} else {
-
val = Number(val);
-
}
-
return val;
-
}
This rather large code snippet parses ActionScript style Object syntax. While this is by no means a complete parser - it was easy to write and saved me a great deal of time on a project recently....
I specifically needed support for 1D and 2D arrays as Object properties. If that weren't the case I would have used something simple like yesterdays method. The array support won't work with anything higher than a 2D array (for now... may fix that soon). For fun I also added nested Object support - this doesn't have any dimensional limitation so you can nest as many objects as you want. For instance.. this works just fine:
-
var gameUser:Object = toObject('{name:"Mr.S", alive:true, stats:{lives:100, points:1200, data:[100,12,40,12,90], plant:{branch:{leaves:["red, "green", "blue"]}}}');
-
-
trace(gameUser.stats.plant.branch.leaves[0]);
-
trace(gameUser.stats.lives);
-
// boolean support
-
trace("not true is false: ", !gameUser.alive);
-
/*outputs:
-
red
-
100
-
not true is false: false
-
*/
You'll also notice the added boolean support in the above example. Which was suggested by katopz in the comments of yesterdays post.
Definitely need to add a word of warning here... I wouldn't be surprised if there were a bug or two lurking in this code. The Objects I've been parsing with it are all quite similar... so use at your own risk.
UPDATEs - Known Issues:
1) fixed a bug where if a String property contains a ,{}[] or : character the parser failed.
4 Comments
Ha ha … great. I’ve tested with very long strings returned from php script… Working great. Excelent work.
cool…. glad to here it’s working nicely with longer strings
The particular syntax of that is called JSON: JavaScript Object Notation, and what you’ve created is a rudimentary JSON parser, with a looser idea of the syntax (object properties should be strings in JSON).
It’s a great format, similar to XML, only more dense, but just as widely (if not more so) supported. However, if you do use this for something, I’d suggest you go with something a little more advanced: [shamelessplug] https://github.com/skyboy/AS3-Utilities/blob/master/skyboy/text/JSON.as [/shamelessplug]
Interesting approach though.
thanks for the feedback skyboy. I’ll be sure to checkout your json parser.