User:LepreKhaun Resident/Json Get Value Safe

From Second Life Wiki
Jump to: navigation, search

<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 ==