User:LepreKhaun Resident/Json Get Value Safe

From Second Life Wiki
Jump to: navigation, search

[NOTE: Pages within my Name Space are a WIP and constantly changing. As my understanding of the problems I attempt to address and the grasp of the subject matter itself deepens, I regularly review what I have written and update the content as better algorithms occur to me.

However, for this process of refinement, improvement and tweaking to result in something that might (hopefully!) benefit the community at large, I ask that comments, suggested improvements, corrections of fact or your own personal style preferences be made ONLY on the Discussion Pages within my Name Space. Thank you!]

<lsl>////////////////////////////// // function string uJsonGetValueSafe (string jsonText, list specifiers) // Same specification as llJsonGetValue() except returns all Strings // enclosed within double quotes and exactly as they appear within jsonText // // Version 1.0 by LepreKhaun 9/9/20 // May be freely used, modified and distributed with this header intact. // Compiled Size = 4,608 bytes ///////////////////////////////

string uJsonGetValueSafe (string jsonText, list specifiers) { string rString = "";

// no need for further processing if not String if (llJsonValueType(jsonText, specifiers) != JSON_STRING) { rString = llJsonGetValue(jsonText, specifiers);

// specifiers may be an empty list and we're dealing with simply a JSON_STRING } else if (llGetListLength(specifiers) == 0) { rString = jsonText;

} else { // used for assembling the return string string char = ""; string prevChar = "";

// boolean flag integer inQuote = FALSE;

// used to step through Array/Object Values // NOTE: Takes valid, compliant Json text for granted integer inArrayObject = 0;

integer iter = 0;

// we need to extract the parent of the String Value list valueSpecifier = llList2List(specifiers, -1, -1);

// shorten specifiers to point to parent of the Value specifiers = llDeleteSubList(specifiers, -1, -1);

// extract the parent jsonText = llJsonGetValue(jsonText, specifiers);

if (llGetListEntryType(valueSpecifier, 0) == TYPE_INTEGER) { // we're dealing with an array integer sPos = llList2Integer(valueSpecifier, 0);

// used to step through array Values integer count = 0;

// find start of our String Value within array while (count < sPos) { char = llGetSubString(jsonText, ++iter, iter); if (char == "\"" && prevChar != "\\") //"// { inQuote = !inQuote; } else if ((char == "[" || char == "{") && !inQuote) { ++inArrayObject; } else if ((char == "]" || char == "}") && !inQuote) { --inArrayObject; } else if (char == "," && !inQuote && !inArrayObject) { ++count; } prevChar = char; } // eat possible white space while ((rString = llGetSubString(jsonText, ++iter, iter)) != "\""){}; // Now assemble return string inQuote = TRUE; prevChar = ""; while (inQuote) { char = llGetSubString(jsonText, ++iter, iter); rString = rString + char; if (char == "\"" && prevChar != "\\") //"// { inQuote = FALSE; } prevChar = char; }

} else { // otherwise, we must be dealing with an object

// make the key for comparison string sKey = llList2String(valueSpecifier, 0);

// and encode it as a JSON_STRING if it's not if (llGetSubString(sKey, 0, 0) != "\"") { sKey = "\"" + sKey + "\""; }

// used for a possible "Key" used in comparison string pKey;

integer jtLength = llStringLength(jsonText) - 1;

while (iter < jtLength) { // go to start of a possible "Key" while (llGetSubString(jsonText, ++iter, iter) != "\"") { };

// form pKey pKey = "\""; inQuote = TRUE; while (inQuote) { char = llGetSubString(jsonText, ++iter, iter); pKey = pKey + char; if (char == "\"" && prevChar != "\\") //"// { inQuote = FALSE; } prevChar = char; }

// move to start of Value, eating possible white space while (llGetSubString(jsonText, ++iter, iter) != ":") { };

char = llEscapeURL(llGetSubString(jsonText, ++iter, iter));

while (char == "%20" || char == "%09" || char == "%0a" || char == "%0d") { char = llEscapeURL(llGetSubString(jsonText, ++iter, iter)); }

char = llUnescapeURL(char);

// check "Key" for match with sKey AND start of a String Value if (pKey == sKey && char == "\"") { // assemble Value prevChar = ""; inQuote = TRUE; rString = "\"";

while (inQuote) { char = llGetSubString(jsonText, ++iter, iter); rString = rString + char; if (char == "\"" && prevChar != "\\") //"// { inQuote = FALSE; } prevChar = char; }

// move to ',' or '}' (next "Key"Value pair or end of object) while(!(llGetSubString(jsonText, ++iter, iter) == "," || llGetSubString(jsonText, iter, iter) == "}")){}; } else { // eat Value to next Key or end of object integer inValue = TRUE; prevChar = ""; inArrayObject = 0; inQuote = FALSE;

while (inValue) { char = llGetSubString(jsonText, iter, iter++); if (char == "\"" && prevChar != "\\") //"// { inQuote = !inQuote; } else if ((char == "," || char == "}") && !inQuote && !inArrayObject) { inValue = FALSE; --iter; } else if ((char == "[" || char == "{") && !inQuote) { ++inArrayObject; } else if ((char == "]" || char == "}") && !inQuote) { --inArrayObject; } prevChar = char; } } } } } return rString; }

// example usage and comparison default { touch_end (integer i){ string jText = "{\"B\":\"Z\",\"C\":[1,\"a\\r\\t\\f\",3],\"A\":\"H\\n\\u23AF\"}"; llOwnerSay(jText); // => '{"B":"Z","C":[1,"a\r\t\f",3],"A":"H\n\u23AF"}'

llOwnerSay(llJsonGetValue(jText, ["A"])); // => 'H' then Unicode character for New Line then 'u23AF' llOwnerSay(uJsonGetValueSafe(jText, ["A"])); // => "H\n\u23AF"

llOwnerSay(llJsonGetValue(jText, ["B"])); // => 'Z' llOwnerSay(uJsonGetValueSafe(jText, ["B"])); // => "Z"

llOwnerSay(llJsonGetValue(jText, ["C"])); // => '[1,"a\r\t\f",3]' llOwnerSay(uJsonGetValueSafe(jText, ["C"])); // => '[1,"a\r\t\f",3]'

llOwnerSay(llJsonGetValue(jText, ["C", 0])); // => '1' llOwnerSay(uJsonGetValueSafe(jText, ["C", 0])); // => '1'

llOwnerSay(llJsonGetValue(jText, ["C", 1])); // => 'a' then Unicode characters for the escaped sequences llOwnerSay(uJsonGetValueSafe(jText, ["C", 1])); // => "a\r\t\f"

llOwnerSay(llJsonGetValue(jText, ["C", 2])); // => '3' llOwnerSay(uJsonGetValueSafe(jText, ["C", 2])); // => '3' } }</lsl>


== More Json Tips, Tricks and Coding Examples ==