{"id":264,"date":"2009-04-24T11:15:45","date_gmt":"2009-04-24T18:15:45","guid":{"rendered":"https:\/\/actionsnippet.com\/?p=1221"},"modified":"2009-04-24T11:15:45","modified_gmt":"2009-04-24T18:15:45","slug":"object-parsing-object-from-string-2","status":"publish","type":"post","link":"https:\/\/actionsnippet.com\/?p=264","title":{"rendered":"Object Parsing (object from string #2)"},"content":{"rendered":"<pre class=\"brush: as3; title: ; notranslate\" title=\"\">\r\nvar str:String = &#039;{numA:100, numB:100, stringA:&quot;hi there&quot;, object:{red:155, green:155, blue: 255}, array1D:&#x5B;1, 2, 3, 4, 5, &quot;six&quot;], array2D:&#x5B;&#x5B;1,0,0], &#x5B;0,1,0], &#x5B;0,0,&quot;z&quot;]], color:0xFF0000}&#039;\r\n\r\nvar obj:Object = toObject(str);\/\/, true); \/\/ comment the &quot;true&quot; in for some debug info\r\n\r\n\/\/ acess every value in the object for testing purposes\r\ntrace(obj.numA);\r\ntrace(obj.numB);\r\ntrace(obj.stringA);\r\ntrace(obj.object.red, obj.object.green, obj.object.blue);\r\ntrace(obj.array1D +&quot; testing access: &quot; + obj.array1D&#x5B;3]);\r\ntrace(obj.array2D + &quot; testing access: &quot; + obj.array2D&#x5B;1] + &quot;  -  &quot; + obj.array2D&#x5B;2]&#x5B;2]);\r\ntrace(obj.color);\r\n\r\n\/*outputs:\r\n100\r\n100\r\nhi there\r\n155 155 255\r\n1,2,3,4,5,six testing access: 4\r\n1,0,0,0,1,0,0,0,z testing access: 0,1,0  -  z\r\n16711680\r\n*\/\r\n \r\nfunction toObject(str:String, debug:Boolean=false):Object{\r\n\tvar cmds:Array = new Array();\r\n\tvar stack:String = &quot;&quot;;\r\n\t\/\/ skip first {\r\n\tstr = str.replace(\/^s+{|^{\/, &quot;&quot;);\r\n\tvar obj:Object = new Object();\r\n\tfor (var i:int = 0; i&lt;str.length; i++){\r\n\t\tvar char:String = str.charAt(i);\r\n\t\tif (char == &quot;:&quot;){\r\n\t\t\tcmds.push(&#x5B;&quot;name:&quot;, stack])\r\n\t\t\tstack = &quot;&quot;;\r\n\t\t\tchar = &quot;&quot;;\r\n\t\t}else\r\n\t\tif (char == &quot;,&quot; || char == &quot;}&quot;){\r\n\t\t\tif (stack != &quot;&quot;){\r\n\t\t\t  cmds.push(&#x5B;&quot;value:&quot;, stack]);\r\n\t\t\t}\r\n\t\t\tstack = &quot;&quot;;\r\n\t\t\tchar = &quot;&quot;;\r\n\t\t}else\r\n\t\tif (char == &#039;&quot;&#039;){\r\n\t\t\tstack = &#039;&quot;&#039;;\r\n\t\t\tfor (j = i + 1; j &lt;str.length; j++){\r\n\t\t\t\tchar = str.charAt(j);\r\n\t\t\t\tstack+=char;\r\n\t\t\t\ti++;\r\n\t\t\t\tif (char == &#039;&quot;&#039;){\r\n\t\t\t\t\t break;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tcmds.push(&#x5B;&quot;value:&quot;, stack]);\r\n\t\t\tstack = &quot;&quot;;\r\n\t\t\tchar = &quot;&quot;;\r\n\t\t}else\r\n\t\tif (char == &quot;{&quot;){\r\n\t\t\tcmds.push(&#x5B;&quot;object:&quot;, stack]);\r\n\t\t\tfor (var j:int = i; j &lt;str.length; j++){\r\n\t\t\t\tchar = str.charAt(j);\r\n\t\t\t\tstack+=char;\r\n\t\t\t\ti++;\r\n\t\t\t\tif (char == &quot;}&quot;){\r\n\t\t\t\t\t break;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tcmds.push(&#x5B;&quot;value:&quot;, stack]);\r\n\t\t\tstack = &quot;&quot;;\r\n\t\t\tchar = &quot;&quot;;\r\n\t\t}else\r\n\t\tif (char == &quot;&#x5B;&quot;){\r\n\t\t\tcmds.push(&#x5B;&quot;array:&quot;, stack]);\r\n\t\t\tstack = &quot;&quot;;\r\n\t\t\tchar = &quot;&quot;;\r\n\t\t}else if (char == &quot;]&quot;){\r\n\t\t\tif (stack != &quot;&quot;){\r\n\t\t\t\tcmds.push(&#x5B;&quot;value:&quot;, stack]);\r\n\t\t\t}\r\n\t\t\tstack = &quot;&quot;;\r\n\t\t\tchar = &quot;&quot;;\r\n\t\t\ti++;\r\n\t\t}\r\n\t\tstack += char;\r\n\t}\r\n\t\/\/ show some debug info\r\n\tif (debug){\r\n\t\tfor (i = 0; i&lt;cmds.length; i++) trace(cmds&#x5B;i]);\r\n\t}\r\n\t\/\/ build the object\r\n\tvar prop:String;\r\n\tvar arrayMode:Boolean = false;\r\n\tvar nest:int = 0;\r\n\tfor (i = 0; i&lt;cmds.length; i++){\r\n\t\tif (cmds&#x5B;i]&#x5B;0] == &quot;name:&quot;){\r\n\t\t\tprop = cmds&#x5B;i]&#x5B;1].replace(\/s\/g, &quot;&quot;);\r\n\t\t\tarrayMode = false;\r\n\t\t\tnest = 0;\r\n\t\t}else if (cmds&#x5B;i]&#x5B;0] == &quot;value:&quot;){\r\n\t\t\tif (arrayMode == false){\r\n\t\t\t  obj&#x5B;prop] = valueType(cmds&#x5B;i]&#x5B;1]);\r\n\t\t\t}else{\r\n\t\t\t\t\/\/ populate array\r\n\t\t\t\tif (nest == 1){\r\n\t\t\t\t  obj&#x5B;prop].push(valueType(cmds&#x5B;i]&#x5B;1]))\r\n\t\t\t\t}else{\r\n\t\t\t\t  obj&#x5B;prop]&#x5B;nest - 2].push(valueType(cmds&#x5B;i]&#x5B;1]))\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}else if (cmds&#x5B;i]&#x5B;0] == &quot;object:&quot;){\r\n\t\t\ti++;\r\n\t\t\tobj&#x5B;prop] = toObject(cmds&#x5B;i]&#x5B;1], debug);\r\n\t\t}else if (cmds&#x5B;i]&#x5B;0] == &quot;array:&quot;){\r\n\t\t\tarrayMode = true;\r\n\t\t\tnest++;\r\n\t\t\tif (nest == 1){\r\n\t\t\t\t\/\/ create array\r\n\t\t\t\tobj&#x5B;prop] = new Array()\r\n\t\t\t}else{\r\n\t\t\t\t\/\/ nested array\r\n\t\t\t\tobj&#x5B;prop].push(new Array());\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\treturn obj;\r\n}\r\n \r\nfunction valueType(val:*):* {\r\n\tif (isNaN(Number(val))) {\r\n\t\t   \/\/ remove leading and trailing white\r\n\t\t   \/\/ remove &quot;&quot; around strings\r\n\t\t   val = val.replace(\/^s+|s+$\/g,&quot;&quot;).replace(\/^&quot;|&quot;$\/g,&quot;&quot;);\r\n\t\t   \/\/  see if it&#039;s a boolean\r\n\t\t   if (val == &quot;true&quot;){\r\n\t\t\t   val = true;\r\n\t\t   }else if (val == &quot;false&quot;){\r\n\t\t\t   val = false\r\n\t\t   }\r\n\t} else {\r\n\t\tval = Number(val);\r\n\t}\r\n\treturn val;\r\n}\r\n<\/pre>\n<p>This rather large code snippet parses ActionScript style Object syntax. While this is by no means a complete parser &#8211; it was easy to write and saved me a great deal of time on a project recently&#8230;.<\/p>\n<p>I specifically needed support for 1D and 2D arrays as Object properties. If that weren&#8217;t the case I would have used something simple like yesterdays method. The array support won&#8217;t work with anything higher than a 2D array (for now&#8230; may fix that soon). For fun I also added nested Object support &#8211; this doesn&#8217;t have any dimensional limitation so you can nest as many objects as you want. For instance.. this works just fine:<\/p>\n<pre class=\"brush: as3; title: ; notranslate\" title=\"\">\r\nvar gameUser:Object = toObject(&#039;{name:&quot;Mr.S&quot;, alive:true, stats:{lives:100, points:1200, data:&#x5B;100,12,40,12,90], plant:{branch:{leaves:&#x5B;&quot;red, &quot;green&quot;, &quot;blue&quot;]}}}&#039;);\r\n\r\ntrace(gameUser.stats.plant.branch.leaves&#x5B;0]);\r\ntrace(gameUser.stats.lives);\r\n\/\/ boolean support\r\ntrace(&quot;not true is false: &quot;, !gameUser.alive);\r\n\/*outputs:\r\nred\r\n100\r\nnot true is false:  false\r\n*\/\r\n<\/pre>\n<p>You&#8217;ll also notice the added boolean support in the above example. Which was suggested by katopz in the comments of yesterdays post.<\/p>\n<p><em>Definitely need to add a word of warning here&#8230; I wouldn&#8217;t be surprised if there were a bug or two lurking in this code. The Objects I&#8217;ve been parsing with it are all quite similar&#8230; so use at your own risk.<\/em><\/p>\n<p>UPDATEs &#8211; Known Issues:<br \/>\n1) fixed a bug where if a String property contains a ,{}[] or : character the parser failed.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>var str:String = &#039;{numA:100, numB:100, stringA:&quot;hi there&quot;, object:{red:155, green:155, blue: 255}, array1D:&#x5B;1, 2, 3, 4, 5, &quot;six&quot;], array2D:&#x5B;&#x5B;1,0,0], &#x5B;0,1,0], &#x5B;0,0,&quot;z&quot;]], color:0xFF0000}&#039; var obj:Object = toObject(str);\/\/, true); \/\/ comment the &quot;true&quot; 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 +&quot; testing access: [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9,20,21],"tags":[3,4],"class_list":["post-264","post","type-post","status-publish","format-standard","hentry","category-dynamic","category-string-manipulation","category-strings","tag-actionscript","tag-flash"],"_links":{"self":[{"href":"https:\/\/actionsnippet.com\/index.php?rest_route=\/wp\/v2\/posts\/264","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/actionsnippet.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/actionsnippet.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/actionsnippet.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/actionsnippet.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=264"}],"version-history":[{"count":0,"href":"https:\/\/actionsnippet.com\/index.php?rest_route=\/wp\/v2\/posts\/264\/revisions"}],"wp:attachment":[{"href":"https:\/\/actionsnippet.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=264"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/actionsnippet.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=264"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/actionsnippet.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=264"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}