Friday, December 31, 2010 at 11:00 AM.
system.verbs.builtins.json.decompile
on decompile (adrtable) { <<Changes <<12/31/10; 10:57:38 AM by DW <<Use the replacetable when encoding, it also converts carriage returns and linefeeds. <<10/24/10; 8:20:06 PM by DW <<Handle empty lists. If we're passed the address of a scalar, then just process a scalar. In other words, don't convert scalars to structs or lists. <<10/23/10; 5:58:25 PM by DW <<Output numbers and booleans without "double quotes" <<10/23/10; 5:18:42 AM by DW <<Add a special case for a table that is a list. See workspace.userlandSamples.jsonTesting.tables.adobeExample1 for a test case. <<10/11/10; 8:43:31 AM by DW <<Encode double-quotes by prefacing them with a backslash. List whose elements were scalars were not being output correctly, that was fixed. <<10/8/10; 3:54:30 PM by DW <<Initial version of a utility that outputs an XML structure in JSON. A general purpose JSONizer. I'm testing it here: http://scripting.com/stories/2010/10/09/nextStepsInTheFeedhoseProj.html local (jsontext = "", indentlevel = 0, emptyName = "<<empty>>"); on add (s) { jsontext = jsontext + string.filledstring ("\t", indentlevel) + s + "\r"}; on droplastcomma () { <<scratchpad.jtx = string.mid (jsontext, sizeof (jsontext) - 10, 11) for i = sizeof (jsontext) downto 1 { if jsontext [i] == "," { jsontext = string.delete (jsontext, i, 1); break}}}; <<scratchpad.jtx = string.mid (jsontext, sizeof (jsontext) - 9, 10) on encode (s) { return (string.multiplereplaceall (s, @json.data.replaceTable))}; <<return (string.replaceall (s, "\"", "\\\"")) //replace " with \" on getnameof (adr) { local (name = nameof (adr^)); if name == "/pcdata" { return ("#value")} else { if name contains "\t" { name = string.nthfield (name, "\t", 2); if name == "" { //10/23/10 by DW name = emptyName}}; return (name)}}; on getscalarstring (adr) { //10/23/10 by DW case typeof (adr^) { stringtype { return ("\"" + encode (string (adr^)) + "\"")}; longtype; doubletype; booleantype { return (encode (string (adr^)))}; listtype { //must be an empty list -- 10/24/10 by DW return ("[ ]")}; unknownType { return ("null")}}}; //10/24/10 by DW on additem (adr, comma="", fllistitem=false) { if nameof (adr^) != "/atts" { if typeof (adr^) == tabletype { name = getnameof (adr); if name != emptyName { //10/23/10 by DW add ("\"" + getnameof (adr) + "\":")}; dotable (adr, comma)} else { if fllistitem { add (getscalarstring (adr) + comma)} else { add ("\"" + getnameof (adr) + "\": " + getscalarstring (adr) + comma)}}}}; on dotable (adrtable, tablelevelcomma="") { local (adr, fllast, comma, countsarray); bundle { //fill countsarray local (adr, adrcount); new (tabletype, @countsarray); for adr in adrtable { adrcount = @countsarray.[getnameof (adr)]; if defined (adrcount^) { adrcount^++} else { adrcount^ = 1}}}; add ("{"); indentlevel++; bundle { //output the attributes first local (adratts = @adrtable^.["/atts"], comma); if defined (adratts^) { for adratt in adratts { add ("\"" + nameof (adratt^) + "\": \"" + encode (string (adratt^)) + "\",")}}}; bundle { //first pass, elements with one occurrence local (adr); for adr in adrtable { if countsarray.[getnameof (adr)] == 1 { bundle { //set comma if indexof (adr^) == sizeof (adrtable^) { //last item in table comma = ","} else { comma = ","}}; additem (adr, comma)}}}; bundle { //second pass, elements with more than one occurrence local (adrcount); for adrcount in @countsarray { if adrcount^ > 1 { local (namethis = nameof (adrcount^)); add ("\"" + namethis + "\": ["); indentlevel++; for adr in adrtable { if getnameof (adr) == namethis { if typeof (adr^) == tabletype { dotable (adr)} else { additem (adr, fllistitem:true)}; add (",")}}; add ("]"); indentlevel--}}}; droplastcomma (); add ("}" + tablelevelcomma); indentlevel--}; if typeof (adrtable^) == tabletype { bundle { //special case for table that is a list, 10/23/10 by DW local (adr, fllist = false); for adr in adrtable { if string.nthfield (nameof (adr^), "\t", 2) == "" { //it's a list fllist = true}; break}; if fllist { add ("["); indentlevel++; for adr in adrtable { additem (adr, ",", fllistitem:true)}; droplastcomma (); add ("]"); indentlevel--; return (jsontext)}}; dotable (adrtable)} else { additem (adrtable, fllistitem:true)}; return (jsontext)} <<bundle //test code <<wp.newtextobject (decompile (@scratchpad.foolishshit), @scratchpad.wpobj) <<wp.newtextobject (decompile (@workspace.userlandSamples.jsonTesting.tables.adobeExample1Variant1), @scratchpad.wpobj) <<webbrowser.displaytext ("<pre>" + decompile (@scratchpad.items) + "</pre>")
This listing is for code that runs in the OPML Editor environment. I created these listings because I wanted the search engines to index it, so that when I want to look up something in my codebase I don't have to use the much slower search functionality in my object database. Dave Winer.