Difference between revisions of "User:LepreKhaun Resident/Json Pretty Printer"
(Version 2.0, major rewrite and way mo' bettah. :)) |
|||
Line 14: | Line 14: | ||
// | // | ||
// A debugging tool for Json construction | // A debugging tool for Json construction | ||
// Version 1.2 | // Version 2.0 by LepreKhaun -- 2013-09-24 | ||
// Complete rewrite w/o recursion and now handles | |||
// escape codes within JSON text correctly | |||
// Version 1.2 -- 2013-07-10 | |||
// Corrected mishandling of quoted numbers. | // Corrected mishandling of quoted numbers. | ||
// Corrected formatting of Key values in json objects. | // Corrected formatting of Key values in json objects. | ||
Line 28: | Line 31: | ||
integer MESSAGE_CHANNEL = 75; | integer MESSAGE_CHANNEL = 75; | ||
// | // helper function | ||
chatThis (string output, integer lvl) { | |||
while (lvl--) output = "\t" + output; | |||
llOwnerSay (output); | |||
chatThis (string | |||
while ( | |||
llOwnerSay ( | |||
} | } | ||
prettyPrint( string jsonText ) { | |||
integer jLength = llStringLength( jsonText ); | |||
string result = ""; | |||
integer level = 0; | |||
integer iter = 0; | integer iter = 0; | ||
integer | string char; | ||
string prevChar; | |||
integer inQuote = FALSE; | |||
while (iter< | while (iter < jLength) { | ||
char = llGetSubString(jsonText, iter, iter++); | |||
if ( | if (char == "\"" && prevChar != "\\") { | ||
if ( | inQuote = !inQuote; | ||
result += char; | |||
} else if (!inQuote) { | |||
if (char == "[" || char == "{" || char == ",") { | |||
chatThis(result + char, level); | |||
result = ""; | |||
if (char != ",") ++level; | |||
} else if (char == "]" || char == "}") { | |||
if (result != "") chatThis(result, level); | |||
--level; | |||
result = char; | |||
} else if (char == ":") { | |||
result += ": "; | |||
} else { | |||
result += char; | |||
} | |||
} else { | |||
result += char; | |||
} | |||
prevChar = char; | |||
} | } | ||
chatThis(result, level); | |||
} | } | ||
Line 108: | Line 79: | ||
{ | { | ||
llOwnerSay ("Hello, " + llKey2Name(llGetOwner())); | llOwnerSay ("Hello, " + llKey2Name(llGetOwner())); | ||
llOwnerSay ("Json Pretty Chat awaits your JSON string"); | llOwnerSay ("Json Pretty Chat V2.0 awaits your JSON string"); | ||
llOwnerSay ("Use " + (string)MESSAGE_CHANNEL + " for the second paramater of"); | llOwnerSay ("Use " + (string)MESSAGE_CHANNEL + " for the second paramater of"); | ||
llOwnerSay ("llMessageLinked\(\) and supply your JSON string in the third."); | llOwnerSay ("llMessageLinked\(\) and supply your JSON string in the third."); | ||
} | } | ||
link_message(integer sender_number, integer number, string message, key id) | link_message(integer sender_number, integer number, string message, key id) | ||
{ | { | ||
if (number == MESSAGE_CHANNEL) { | if (number == MESSAGE_CHANNEL) { | ||
llOwnerSay("Pretty Chat of: " + message); | llOwnerSay("Pretty Chat of: " + message); | ||
prettyPrint(message); | |||
} | } | ||
} | } | ||
Line 124: | Line 95: | ||
Harness program, showing usage: | Harness program, showing usage: | ||
<lsl> | <lsl> | ||
default | default | ||
Line 131: | Line 103: | ||
llOwnerSay("Hello, Avatar!"); | llOwnerSay("Hello, Avatar!"); | ||
} | } | ||
touch_start(integer total_number) | touch_start(integer total_number) | ||
{ | { | ||
// Used as a "channel ID' for link messages | // Used as a "channel ID' for link messages | ||
integer MESSAGE_CHANNEL = 75; | integer MESSAGE_CHANNEL = 75; | ||
string source = | // http://www.codeproject.com/Articles/426142/JSON-Pretty-Print-and-JSON-Multi-level-Collapse-Co | ||
// From Heading: "Pretty Print" Code in JavaScript | |||
string source = | |||
"{\"apiVersion\":\"2.0\",\"data\":{\"updated\":\"2010-01-07T19:58:42.949Z\",\"totalItems\":800," + | |||
"\"startIndex\":1,\"itemsPerPage\":1,\"items\":[{\"id\":\"hYB0mn5zh2c\",\"uploaded\":" + | |||
"\"2007-06-05T22:07:03.000Z\",\"updated\":\"2010-01-07T13:26:50.000Z\"," + | |||
"\"uploader\":\"GoogleDeveloperDay\",\"category\":\"News\",\"title\":\"Google Developers Day US" + | |||
" - Maps API Introduction\",\"description\":\"Google Maps API Introduction...\",\"tags\":" + | |||
"[\"GDD07\",\"GDD07US\",\"Maps\"],\"thumbnail\":{\"default\":\"http://i.ytimg.com/vi/" + | |||
"hYB0mn5zh2c/default.jpg\",\"hqDefault\":\"http://i.ytimg.com/vi/hYB0mn5zh2c/hqdefault.jpg\"}," + | |||
"\"player\":{\"default\":\"https://www.youtube.com/watch?v=hYB0mn5zh2c\",\"mobile\":" + | |||
"\"https://m.youtube.com/details?v=hYB0mn5zh2c\"},\"content\":{\"1\":\"rtsp://v5.cache3.c." + | |||
"youtube.com/CiILENy.../0/0/0/video.3gp\",\"5\":\"http://www.youtube.com/v/hYB0mn5zh2c?" + | |||
"f...\",\"6\":\"rtsp://v1.cache1.c.youtube.com/CiILENy.../0/0/0/video.3gp\"},\"duration\":2840," + | |||
"\"aspectRatio\":\"widescreen\",\"likeCount\":171,\"rating\":4.63,\"ratingCount\":68,\"viewCount" + | |||
"\":220101,\"favoriteCount\":201,\"commentCount\":22,\"status\":{\"value\":\"restricted\"," + | |||
"\"reason\":\"limitedSyndication\"},\"accessControl\":{\"syndicate\":\"allowed\"," + | |||
"\"commentVote\":\"allowed\",\"rate\":\"allowed\",\"list\":\"allowed\",\"comment\":\"allowed\"," + | |||
"\"embed\":\"allowed\",\"videoRespond\":\"moderated\"}}]}}"; | |||
llMessageLinked (LINK_THIS, MESSAGE_CHANNEL, source, NULL_KEY); | llMessageLinked (LINK_THIS, MESSAGE_CHANNEL, source, NULL_KEY); | ||
} | } | ||
Line 147: | Line 137: | ||
<pre> | <pre> | ||
Object: Hello, LepreKhaun Resident | Object: Hello, LepreKhaun Resident | ||
Object: Json Pretty Chat is waiting for your JSON string | Object: Json Pretty Chat V2.0 is waiting for your JSON string | ||
Object: Use 75 for the second paramater of | Object: Use 75 for the second paramater of | ||
Object: llMessageLinked() and supply your JSON string in the third. | Object: llMessageLinked() and supply your JSON string in the third. | ||
Line 155: | Line 145: | ||
// Result of touch_start() | // Result of touch_start() | ||
Object: { | Object: { | ||
Object: " | Object: "apiVersion": "2.0", | ||
Object: " | Object: "data": { | ||
Object: 1, | Object: "updated": "2010-01-07T19:58:42.949Z", | ||
Object: | Object: "totalItems": 800, | ||
Object: | Object: "startIndex": 1, | ||
Object: | Object: "itemsPerPage": 1, | ||
Object: "items": [ | |||
Object: { | |||
Object: "id": "hYB0mn5zh2c", | |||
Object: "uploaded": "2007-06-05T22:07:03.000Z", | |||
Object: "updated": "2010-01-07T13:26:50.000Z", | |||
Object: "uploader": "GoogleDeveloperDay", | |||
Object: "category": "News", | |||
Object: "title": "Google Developers Day US - Maps API Introduction", | |||
Object: "description": "Google Maps API Introduction...", | |||
Object: "tags": [ | |||
Object: "GDD07", | |||
Object: "GDD07US", | |||
Object: "Maps" | |||
Object: ], | |||
Object: "thumbnail": { | |||
Object: "default": "http://i.ytimg.com/vi/hYB0mn5zh2c/default.jpg", | |||
Object: "hqDefault": "http://i.ytimg.com/vi/hYB0mn5zh2c/hqdefault.jpg" | |||
Object: }, | |||
Object: "player": { | |||
Object: "default": "https://www.youtube.com/watch?v=hYB0mn5zh2c", | |||
Object: "mobile": "https://m.youtube.com/details?v=hYB0mn5zh2c" | |||
Object: }, | |||
Object: "content": { | |||
Object: "1": "rtsp://v5.cache3.c.youtube.com/CiILENy.../0/0/0/video.3gp", | |||
Object: "5": "http://www.youtube.com/v/hYB0mn5zh2c?f...", | |||
Object: "6": "rtsp://v1.cache1.c.youtube.com/CiILENy.../0/0/0/video.3gp" | |||
Object: }, | |||
Object: "duration": 2840, | |||
Object: "aspectRatio": "widescreen", | |||
Object: "likeCount": 171, | |||
Object: "rating": 4.63, | |||
Object: "ratingCount": 68, | |||
Object: "viewCount": 220101, | |||
Object: "favoriteCount": 201, | |||
Object: "commentCount": 22, | |||
Object: "status": { | |||
Object: "value": "restricted", | |||
Object: "reason": "limitedSyndication" | |||
Object: }, | |||
Object: "accessControl": { | |||
Object: "syndicate": "allowed", | |||
Object: "commentVote": "allowed", | |||
Object: "rate": "allowed", | |||
Object: "list": "allowed", | |||
Object: "comment": "allowed", | |||
Object: "embed": "allowed", | |||
Object: "videoRespond": "moderated" | |||
Object: } | |||
Object: } | |||
Object: ] | |||
Object: } | |||
Object: } | Object: } | ||
</pre> | </pre> |
Revision as of 07:07, 24 September 2013
[NOTE: Since I refrain from rearranging the flamingos in front of your trailer home, you are expected to extend the courtesy and leave comments, suggested improvements, corrections of fact or your own personal preferences ONLY on the Discussion Pages within my Name Space. Thank you!]
JsonPrettyChat.lsl - a JSON Pretty Printer
This is a stand alone debugging tool for working with JSON text. It acts like all JSON pretty printers and outputs to llOwnerSay(). This is NOT a JSON validator, meaning it may well "pretty print" your string even if your strings within it are mal-formed json constructions (such as having "\s" within it or empty values such as "[,,,]", which breaks strict JSON compliance). But, it will separate your strings out for visual inspection.
It uses recursion A LOT so will likely crash if you have a very large JSON structure. However, it'll have worked it up to a point where you can determine where it hit the stack heap collision, and you simply need to break parts of the JSON string out to continue deeper into it.
It expects a link message with the JSON string as the third parameter. The second parameter is used as a "channel ID" (defaults to 75 as written). If this conflicts with your existing link messaging system, I'd expect you should see how to modify the code to suit yourself.
<lsl> //////////////////////////////////////////////////// // JsonPrettyChat.lsl // // A debugging tool for Json construction // Version 2.0 by LepreKhaun -- 2013-09-24 // Complete rewrite w/o recursion and now handles // escape codes within JSON text correctly // Version 1.2 -- 2013-07-10 // Corrected mishandling of quoted numbers. // Corrected formatting of Key values in json objects. // Version 1.0 Released -- 2013-07-09 // // Usage: Place this stand-alone script within object containing program // you wish to debug and address it with // llMessageLinked ( integer LINK_SET, integer MESSAGE_CHANNEL, string json, key NULL_KEY ); // at the point(s) you wish to review the JSON string. ////////////////////////////////////////////////////
// Used as a "channel ID' for link messages integer MESSAGE_CHANNEL = 75;
// helper function chatThis (string output, integer lvl) { while (lvl--) output = "\t" + output; llOwnerSay (output); }
prettyPrint( string jsonText ) { integer jLength = llStringLength( jsonText ); string result = ""; integer level = 0; integer iter = 0; string char; string prevChar; integer inQuote = FALSE;
while (iter < jLength) { char = llGetSubString(jsonText, iter, iter++); if (char == "\"" && prevChar != "\\") { inQuote = !inQuote; result += char; } else if (!inQuote) { if (char == "[" || char == "{" || char == ",") { chatThis(result + char, level); result = ""; if (char != ",") ++level; } else if (char == "]" || char == "}") { if (result != "") chatThis(result, level); --level; result = char; } else if (char == ":") { result += ": "; } else { result += char; } } else { result += char; } prevChar = char; } chatThis(result, level); }
// Main Program default { state_entry() { llOwnerSay ("Hello, " + llKey2Name(llGetOwner())); llOwnerSay ("Json Pretty Chat V2.0 awaits your JSON string"); llOwnerSay ("Use " + (string)MESSAGE_CHANNEL + " for the second paramater of"); llOwnerSay ("llMessageLinked\(\) and supply your JSON string in the third."); }
link_message(integer sender_number, integer number, string message, key id) { if (number == MESSAGE_CHANNEL) { llOwnerSay("Pretty Chat of: " + message); prettyPrint(message); } } } </lsl>
Harness program, showing usage:
<lsl> default {
state_entry() { llOwnerSay("Hello, Avatar!"); } touch_start(integer total_number) { // Used as a "channel ID' for link messages integer MESSAGE_CHANNEL = 75; // http://www.codeproject.com/Articles/426142/JSON-Pretty-Print-and-JSON-Multi-level-Collapse-Co // From Heading: "Pretty Print" Code in JavaScript string source =
"{\"apiVersion\":\"2.0\",\"data\":{\"updated\":\"2010-01-07T19:58:42.949Z\",\"totalItems\":800," + "\"startIndex\":1,\"itemsPerPage\":1,\"items\":[{\"id\":\"hYB0mn5zh2c\",\"uploaded\":" + "\"2007-06-05T22:07:03.000Z\",\"updated\":\"2010-01-07T13:26:50.000Z\"," + "\"uploader\":\"GoogleDeveloperDay\",\"category\":\"News\",\"title\":\"Google Developers Day US" + " - Maps API Introduction\",\"description\":\"Google Maps API Introduction...\",\"tags\":" + "[\"GDD07\",\"GDD07US\",\"Maps\"],\"thumbnail\":{\"default\":\"http://i.ytimg.com/vi/" + "hYB0mn5zh2c/default.jpg\",\"hqDefault\":\"http://i.ytimg.com/vi/hYB0mn5zh2c/hqdefault.jpg\"}," + "\"player\":{\"default\":\"https://www.youtube.com/watch?v=hYB0mn5zh2c\",\"mobile\":" + "\"https://m.youtube.com/details?v=hYB0mn5zh2c\"},\"content\":{\"1\":\"rtsp://v5.cache3.c." + "youtube.com/CiILENy.../0/0/0/video.3gp\",\"5\":\"http://www.youtube.com/v/hYB0mn5zh2c?" + "f...\",\"6\":\"rtsp://v1.cache1.c.youtube.com/CiILENy.../0/0/0/video.3gp\"},\"duration\":2840," + "\"aspectRatio\":\"widescreen\",\"likeCount\":171,\"rating\":4.63,\"ratingCount\":68,\"viewCount" + "\":220101,\"favoriteCount\":201,\"commentCount\":22,\"status\":{\"value\":\"restricted\"," + "\"reason\":\"limitedSyndication\"},\"accessControl\":{\"syndicate\":\"allowed\"," + "\"commentVote\":\"allowed\",\"rate\":\"allowed\",\"list\":\"allowed\",\"comment\":\"allowed\"," + "\"embed\":\"allowed\",\"videoRespond\":\"moderated\"}}]}}";
llMessageLinked (LINK_THIS, MESSAGE_CHANNEL, source, NULL_KEY); }
} </lsl>
Outputs:
Object: Hello, LepreKhaun Resident Object: Json Pretty Chat V2.0 is waiting for your JSON string Object: Use 75 for the second paramater of Object: llMessageLinked() and supply your JSON string in the third. // Harness program checking in. Object: Hello, Avatar! // Result of touch_start() Object: { Object: "apiVersion": "2.0", Object: "data": { Object: "updated": "2010-01-07T19:58:42.949Z", Object: "totalItems": 800, Object: "startIndex": 1, Object: "itemsPerPage": 1, Object: "items": [ Object: { Object: "id": "hYB0mn5zh2c", Object: "uploaded": "2007-06-05T22:07:03.000Z", Object: "updated": "2010-01-07T13:26:50.000Z", Object: "uploader": "GoogleDeveloperDay", Object: "category": "News", Object: "title": "Google Developers Day US - Maps API Introduction", Object: "description": "Google Maps API Introduction...", Object: "tags": [ Object: "GDD07", Object: "GDD07US", Object: "Maps" Object: ], Object: "thumbnail": { Object: "default": "http://i.ytimg.com/vi/hYB0mn5zh2c/default.jpg", Object: "hqDefault": "http://i.ytimg.com/vi/hYB0mn5zh2c/hqdefault.jpg" Object: }, Object: "player": { Object: "default": "https://www.youtube.com/watch?v=hYB0mn5zh2c", Object: "mobile": "https://m.youtube.com/details?v=hYB0mn5zh2c" Object: }, Object: "content": { Object: "1": "rtsp://v5.cache3.c.youtube.com/CiILENy.../0/0/0/video.3gp", Object: "5": "http://www.youtube.com/v/hYB0mn5zh2c?f...", Object: "6": "rtsp://v1.cache1.c.youtube.com/CiILENy.../0/0/0/video.3gp" Object: }, Object: "duration": 2840, Object: "aspectRatio": "widescreen", Object: "likeCount": 171, Object: "rating": 4.63, Object: "ratingCount": 68, Object: "viewCount": 220101, Object: "favoriteCount": 201, Object: "commentCount": 22, Object: "status": { Object: "value": "restricted", Object: "reason": "limitedSyndication" Object: }, Object: "accessControl": { Object: "syndicate": "allowed", Object: "commentVote": "allowed", Object: "rate": "allowed", Object: "list": "allowed", Object: "comment": "allowed", Object: "embed": "allowed", Object: "videoRespond": "moderated" Object: } Object: } Object: ] Object: } Object: }