Difference between revisions of "LlJsonSetValue"

From Second Life Wiki
Jump to: navigation, search
(Added extensive examples of usage.)
m (reformatted example script for better readability on mobile screens and a more modular approach for easier expandability)
Line 21: Line 21:
 
|spec=See [[Json_usage_in_LSL]]
 
|spec=See [[Json_usage_in_LSL]]
 
|constants
 
|constants
|examples=<lsl>string jsonText = "[9,\"<1,1,1>\",false,{\"A\":8,\"Z\":9}]";
+
|examples=
 +
<lsl>
 +
string TEST_STRING_JSON;
  
default
+
init()
 
{
 
{
 +
    TEST_STRING_JSON = "[9,\"<1,1,1>\",false,{\"A\":8,\"Z\":9}]";
  
state_entry()
+
// [9,"<1,1,1>",false,{"A":8,"Z":9}]
{
+
    say("Original TEST_STRING_JSON: " + TEST_STRING_JSON);
  llOwnerSay("Json Text: " + jsonText); // [9,"<1,1,1>",false,{"A":8,"Z":9}]
+
}
}
+
 
+
run_json_test(string input)
touch_end(integer n)
+
{
{
+
    string output;
string tempText;
+
 
+
// changing values within the json string
//////////////
+
 
// Changing Values within the Json text
+
// change the first value in the array to 10
//////////////
+
    output = llJsonSetValue(input, [0], "10");
+
 
// Change the first value in the array to 10
+
// [10,"<1,1,1>",false,{"A":8,"Z":9}]
tempText = llJsonSetValue(jsonText, [0], "10");
+
    say("( 1): " + output);
llOwnerSay("( 1): " + tempText); // [10,"<1,1,1>",false,{"A":8,"Z":9}]
+
 
+
// change the third value in the array to 'true'
//Change the third value in the array to 'true'
+
    output = llJsonSetValue(input, [2], JSON_TRUE);
tempText = llJsonSetValue(jsonText, [2], JSON_TRUE);
+
 
llOwnerSay("( 2): " + tempText); // [9,"<1,1,1>",true,{"A":8,"Z":9}]
+
// [9,"<1,1,1>",true,{"A":8,"Z":9}]
+
    say("( 2): " + output);
// Change the value of "A" within the Json object to 3
+
 
tempText = llJsonSetValue(jsonText, [3, "A"], "3");
+
// change the value of "A" within the Json object to 3
llOwnerSay("( 3): " + tempText); // [9,"<1,1,1>",false,{"A":3,"Z":9}]
+
    output = llJsonSetValue(input, [3, "A"], "3");
+
 
//////////////
+
// [9,"<1,1,1>",false,{"A":3,"Z":9}]
// Adding a Value or new "Key":Value pair within the Json text
+
    say("( 3): " + output);
//////////////
+
 
+
// adding a value or new key-value-pair within the input
// Add the Value "Hello" to the end of the array
+
 
// NOTE: One cannot insert, only add to the end
+
// add the value "Hello" to the end of the array
tempText = llJsonSetValue(jsonText, [JSON_APPEND], "Hello");
+
//     NOTE: One cannot insert, only add to the end
llOwnerSay("( 4): " + tempText); // [9,"<1,1,1>",false,{"A":8,"Z":9},"Hello"]
+
    output = llJsonSetValue(input, [JSON_APPEND], "Hello");
+
 
// Add the "Key":Value pair "B":10 to the object
+
// [9,"<1,1,1>",false,{"A":8,"Z":9},"Hello"]
tempText = llJsonSetValue(jsonText, [3, "B"], "10");
+
    say("( 4): " + output);
llOwnerSay("( 5): " + tempText); // [9,"<1,1,1>",false,{"A":8,"B":10,"Z":9}]
+
 
+
// add the key-value-pair "B":10 to the object
//////////////
+
    output = llJsonSetValue(input, [3, "B"], "10");
// Things to look out for when modifying Json text
+
 
// (*** Be careful when using this function! ***)
+
// [9,"<1,1,1>",false,{"A":8,"B":10,"Z":9}]
//////////////
+
    say("( 5): " + output);
+
 
// Out of bounds array assignments
+
 
// Defined as attempting to add a Value to a position ...
+
// Things to look out for when modifying Json text
// ...greater than the length of the array (which may be 0)
+
//     ~!~ Be careful when using this function ~!~
// JSON_APPEND is ALWAYS the preferred way to add to an array
+
 
tempText = llJsonSetValue(jsonText, [5], "10");
+
// out of bounds array assignment:
llOwnerSay("( 6): " + llEscapeURL(tempText)); // %EF%B7%90 (URL escaped JSON_INVALID)
+
//     defined as attempting to add a value to a position ...
+
//     ...greater than the length of the array (which may be 0)
// BUT, this works, since it is in bounds
+
//     JSON_APPEND is ALWAYS the preferred way to add to an array
// (eqivalent to JSON_APPEND in this case)
+
    output = llJsonSetValue(input, [5], "10");
tempText = llJsonSetValue(jsonText, [4], "10");
+
 
llOwnerSay("( 7): " + tempText); // [9,"<1,1,1>",false,{"A":8,"Z":9},10]
+
// %EF%B7%90 (URL escaped JSON_INVALID)
+
    say("( 6): " + llEscapeURL(output));
// Careless formation of new arrays
+
 
// ( the 4 and all subsequent 0's are all in bounds.)
+
// BUT, this works, since it is in bounds
tempText = llJsonSetValue(jsonText, [4,0,0,0], "10");
+
//     (eqivalent to JSON_APPEND in this case)
llOwnerSay("( 8): " + tempText); // [9,"<1,1,1>",false,{"A":8,"Z":9},[[[10]]]]
+
    output = llJsonSetValue(input, [4], "10");
+
 
// Overwriting an object with an array
+
// [9,"<1,1,1>",false,{"A":8,"Z":9},10]
// Mistaken use of JSON_APPEND on an object
+
    say("( 7): " + output);
tempText = llJsonSetValue(jsonText, [3, JSON_APPEND], "10");
+
 
llOwnerSay("( 9): " + tempText); // [9,"<1,1,1>",false,[10]]
+
// careless formation of new arrays
+
//     ( the 4 and all subsequent 0's are all in bounds.)
// Careless formation of new objects
+
    output = llJsonSetValue(input, [4, 0, 0, 0], "10");
// NOTE: "Key" assignemts will NEVER result in a return of JSON_INVALID!
+
 
tempText = llJsonSetValue(jsonText, [3, "W", "X"], "10");
+
// [9,"<1,1,1>",false,{"A":8,"Z":9},[[[10]]]]
llOwnerSay("(10): " + tempText); //  [9,"<1,1,1>",false,{"A":8,"W":{"X":10},"Z":9}]
+
    say("( 8): " + output);
tempText = llJsonSetValue(jsonText, [3, "W", "X", "Y"], "10");
+
 
llOwnerSay("(11): " + tempText); //  [9,"<1,1,1>",false,{"A":8,"W":{"X":{"Y":10}},"Z":9}]
+
// overwriting an object with an array:
 +
//     ~!~ mistaken use of JSON_APPEND on an object ~!~
 +
    output = llJsonSetValue(input, [3, JSON_APPEND], "10");
 +
 
 +
// [9,"<1,1,1>",false,[10]]
 +
    say("( 9): " + output);
 +
 
 +
// careless formation of new objects
 +
//     NOTE: "Key" assignemts will NEVER result in a return of JSON_INVALID!
 +
    output = llJsonSetValue(input, [3, "W", "X"], "10");
 +
 
 +
//  [9,"<1,1,1>",false,{"A":8,"W":{"X":10},"Z":9}]
 +
    say("(10): " + output);
 +
 
 +
    output = llJsonSetValue(input, [3, "W", "X", "Y"], "10");
 +
 
 +
//  [9,"<1,1,1>",false,{"A":8,"W":{"X":{"Y":10}},"Z":9}]
 +
    say("(11): " + output);
 +
 
 +
//  overwriting an array with an object
 +
    output = llJsonSetValue(input, ["X"], "10");
 +
 
 +
//  {"X":10}
 +
    say("(12): " + output);
 +
 
 +
//  special case considerations:
 +
 
 +
 
 +
//  BUG-3692:
 +
//      a bug where, instead of JSON_INVALID being returned, if the out of
 +
//      bounds index is at a lower level than the topmost (root) level, a
 +
//      non-compliant JSON text will be formed
 +
    output = llJsonSetValue(input, [1, 7], "Disappearing Text");
 +
 
 +
//  Note the "empty" second position in resulting array
 +
//  [9,,false,{"A":8,"Z":9}]
 +
    say("(13): " + output);
 +
 
 +
//  though there is no way to directly delete a key-value-pair
 +
//  nor remove a value from an array,
 +
//  the use of JSON_NULL may prove adequate
 +
    output = llJsonSetValue(input, [3, "A"], JSON_NULL);
 +
 
 +
//  [9,"<1,1,1>",false,{"A":null,"Z":9}]
 +
    say("(14): " + output);
 +
 
 +
//  if a JSON text object has been formed with llList2Json()
 +
//  that contains one or more duplicated "Keys", (allowable
 +
//  but NOT recommended!) ANY change
 +
//  made to that object will correct the condition,
 +
//  with all but the last such "Key" being removed
 +
    output = llList2Json(JSON_OBJECT, ["A", 1, "A", 2, "A", 3, "B", 4, "B", 4]);
 +
 
 +
//  both Keys "A" and "B" are duplicated
 +
//  {"A":1,"A":2,"A":3,"B":4,"B":4}
 +
    say("(15): " + output);
 +
 
 +
//  only the last value of the duplications is accessable though
 +
 
 +
//  3
 +
    say("(16): " + llJsonGetValue(output, ["A"]));
 +
 
 +
//  condition corrected by adding a key-value-pair...
 +
 
 +
//  {"A":3,"B":4,"Z":5}
 +
    say("(17): " + llJsonSetValue(output, ["Z"], "5"));
 +
 
 +
//  ... or by changing a value
 +
 
 +
// {"A":5,"B":4}
 +
    say("(18): " + llJsonSetValue(output, ["A"], "5"));
 +
}
 +
 
 +
say(string message)
 +
{
 +
    llOwnerSay(message);
 +
//  llRegionSayTo(llGetOwner(), PUBLIC_CHANNEL, message);
 +
//  llWhisper(PUBLIC_CHANNEL, message);
 +
}
 +
 
 +
default
 +
{
 +
    on_rez(integer start_param)
 +
    {
 +
        llResetScript();
 +
    }
  
// Overwriting an array with an object
+
    state_entry()
tempText = llJsonSetValue(jsonText, ["X"], "10");
+
    {
llOwnerSay("(12): " + tempText); // {"X":10}
+
        init();
+
    }
//////////////
+
// Special case considerations
+
//////////////
+
+
// There is currently a bug (BUG-3692) where, instead of JSON_INVALID
+
// being returned, if the out of bounds index is at a lower level than
+
// the topmost (root) level, a non-compliant Json text will be formed
+
tempText = llJsonSetValue(jsonText, [1, 7], "Disappearing Text");
+
// Note the "empty" second position in resulting array
+
llOwnerSay("(13): " + tempText); // [9,,false,{"A":8,"Z":9}]
+
+
// though there is no way to directly delete a "Key":Value pair
+
// nor remove a Value from an array,
+
// The use of JSON_NULL may prove adequate
+
tempText = llJsonSetValue(jsonText, [3, "A"], JSON_NULL);
+
llOwnerSay("(14): " + tempText); // [9,"<1,1,1>",false,{"A":null,"Z":9}]
+
+
// if a Json text object has been formed with llList2Json()
+
// that contains one or more duplicated "Keys", (allowable
+
// but NOT recommended!) ANY change
+
// made to that object will correct the condition,
+
// with all but the last such "Key" being removed
+
tempText = llList2Json(JSON_OBJECT, ["A", 1, "A", 2, "A", 3, "B", 4, "B", 4]);
+
// both Keys "A" and "B" are duplicated
+
llOwnerSay("(15): " + tempText); // {"A":1,"A":2,"A":3,"B":4,"B":4}
+
// Only the last value of the duplications is accessable though
+
llOwnerSay("(16): " + llJsonGetValue(tempText, ["A"])); // 3
+
// Condition corrected by adding a "Key":Value pair...
+
llOwnerSay("(17): " + llJsonSetValue(tempText, ["Z"], "5")); // {"A":3,"B":4,"Z":5}
+
// ..or by changing a Value
+
llOwnerSay("(18): " + llJsonSetValue(tempText, ["A"], "5")); //{"A":5,"B":4}
+
}
+
}</lsl>
+
  
 +
    touch_end(integer num_detected)
 +
    {
 +
//      copy 'TEST_STRING_JSON' from the following function call
 +
//      to the string 'input' in the function declaration
 +
//      and run a test on 'input' to not (!) modify 'TEST_STRING_JSON'
 +
//      but its copy instead
 +
        run_json_test(TEST_STRING_JSON);
 +
    }
 +
}
 +
</lsl>
 
|caveats=
 
|caveats=
 
|helpers
 
|helpers

Revision as of 10:12, 23 September 2013

Summary

Function: string llJsonSetValue( string json, list specifiers, string value );

Returns, if successful, a new JSON text string which is json with the value indicated by the specifiers list set to value.

If unsuccessful (usually because of specifying an out of range array index) it should, and usually will, return JSON_INVALID. However this is currently, 8/20/2013, broken at depths lower than the topmost level, where it will silently invalidate the return string, so be careful! The return string should always be checked for JSON_INVALID before overwriting the original Json text.

An "out of range array index" is defined to be any Integer specifier greater than the length of an existing array at that level within the Json text or greater than 0 (zero) at a level an array doesn't exist.

A special specifier, JSON_APPEND, is accepted which appends the value to the end of the array at the specified level. Care should be taken- if that level is not an array, the existing Value there will be overwritten and replaced with an array containing value at it's first (0) index.

Contrary to LSL_List, negative indexing of Json arrays is not supported.

If an existing "Key" is specified at that level, its Value will be overwritten by value, otherwise a new "Key":Value pair will be formed within the Json object.

If value is JSON_TRUE, JSON_FALSE or JSON_NULL, the Value set will be the bare words 'true', 'false' or 'null', respectively, at the specified location within json.
Returns a string

• string json
• list specifiers
• string value

Specification

Examples

<lsl> string TEST_STRING_JSON;

init() {

   TEST_STRING_JSON = "[9,\"<1,1,1>\",false,{\"A\":8,\"Z\":9}]";

// [9,"<1,1,1>",false,{"A":8,"Z":9}]

   say("Original TEST_STRING_JSON: " + TEST_STRING_JSON);

}

run_json_test(string input) {

   string output;

// changing values within the json string

// change the first value in the array to 10

   output = llJsonSetValue(input, [0], "10");

// [10,"<1,1,1>",false,{"A":8,"Z":9}]

   say("( 1): " + output);

// change the third value in the array to 'true'

   output = llJsonSetValue(input, [2], JSON_TRUE);

// [9,"<1,1,1>",true,{"A":8,"Z":9}]

   say("( 2): " + output);

// change the value of "A" within the Json object to 3

   output = llJsonSetValue(input, [3, "A"], "3");

// [9,"<1,1,1>",false,{"A":3,"Z":9}]

   say("( 3): " + output);

// adding a value or new key-value-pair within the input

// add the value "Hello" to the end of the array // NOTE: One cannot insert, only add to the end

   output = llJsonSetValue(input, [JSON_APPEND], "Hello");

// [9,"<1,1,1>",false,{"A":8,"Z":9},"Hello"]

   say("( 4): " + output);

// add the key-value-pair "B":10 to the object

   output = llJsonSetValue(input, [3, "B"], "10");

// [9,"<1,1,1>",false,{"A":8,"B":10,"Z":9}]

   say("( 5): " + output);


// Things to look out for when modifying Json text // ~!~ Be careful when using this function ~!~

// out of bounds array assignment: // defined as attempting to add a value to a position ... // ...greater than the length of the array (which may be 0) // JSON_APPEND is ALWAYS the preferred way to add to an array

   output = llJsonSetValue(input, [5], "10");

//  %EF%B7%90 (URL escaped JSON_INVALID)

   say("( 6): " + llEscapeURL(output));

// BUT, this works, since it is in bounds // (eqivalent to JSON_APPEND in this case)

   output = llJsonSetValue(input, [4], "10");

// [9,"<1,1,1>",false,{"A":8,"Z":9},10]

   say("( 7): " + output);

// careless formation of new arrays // ( the 4 and all subsequent 0's are all in bounds.)

   output = llJsonSetValue(input, [4, 0, 0, 0], "10");

// [9,"<1,1,1>",false,{"A":8,"Z":9},[[[10]]]]

   say("( 8): " + output);

// overwriting an object with an array: // ~!~ mistaken use of JSON_APPEND on an object ~!~

   output = llJsonSetValue(input, [3, JSON_APPEND], "10");

// [9,"<1,1,1>",false,[10]]

   say("( 9): " + output);

// careless formation of new objects // NOTE: "Key" assignemts will NEVER result in a return of JSON_INVALID!

   output = llJsonSetValue(input, [3, "W", "X"], "10");

// [9,"<1,1,1>",false,{"A":8,"W":{"X":10},"Z":9}]

   say("(10): " + output);
   output = llJsonSetValue(input, [3, "W", "X", "Y"], "10");
// [9,"<1,1,1>",false,{"A":8,"W":{"X":{"Y":10

Deep Notes

All Issues

~ Search JIRA for related Issues
   JSON_NULL may be deceptively returned instead of JSON_INVALID when noncompliant Json text is encountered by either llJsonValueType or llJsonGetValue. Fixed with release 13.09.21.281328.

Signature

function string llJsonSetValue( string json, list specifiers, string value );
,"Z":9}]
   say("(11): " + output);

// overwriting an array with an object

   output = llJsonSetValue(input, ["X"], "10");

// {"X":10}

   say("(12): " + output);

// special case considerations:


// BUG-3692: // a bug where, instead of JSON_INVALID being returned, if the out of // bounds index is at a lower level than the topmost (root) level, a // non-compliant JSON text will be formed

   output = llJsonSetValue(input, [1, 7], "Disappearing Text");

// Note the "empty" second position in resulting array // [9,,false,{"A":8,"Z":9}]

   say("(13): " + output);

// though there is no way to directly delete a key-value-pair // nor remove a value from an array, // the use of JSON_NULL may prove adequate

   output = llJsonSetValue(input, [3, "A"], JSON_NULL);

// [9,"<1,1,1>",false,{"A":null,"Z":9}]

   say("(14): " + output);

// if a JSON text object has been formed with llList2Json() // that contains one or more duplicated "Keys", (allowable // but NOT recommended!) ANY change // made to that object will correct the condition, // with all but the last such "Key" being removed

   output = llList2Json(JSON_OBJECT, ["A", 1, "A", 2, "A", 3, "B", 4, "B", 4]);

// both Keys "A" and "B" are duplicated // {"A":1,"A":2,"A":3,"B":4,"B":4}

   say("(15): " + output);

// only the last value of the duplications is accessable though

// 3

   say("(16): " + llJsonGetValue(output, ["A"]));

// condition corrected by adding a key-value-pair...

// {"A":3,"B":4,"Z":5}

   say("(17): " + llJsonSetValue(output, ["Z"], "5"));

// ... or by changing a value

// {"A":5,"B":4}

   say("(18): " + llJsonSetValue(output, ["A"], "5"));

}

say(string message) {

   llOwnerSay(message);

// llRegionSayTo(llGetOwner(), PUBLIC_CHANNEL, message); // llWhisper(PUBLIC_CHANNEL, message); }

default {

   on_rez(integer start_param)
   {
       llResetScript();
   }
   state_entry()
   {
       init();
   }
   touch_end(integer num_detected)
   {

// copy 'TEST_STRING_JSON' from the following function call // to the string 'input' in the function declaration // and run a test on 'input' to not (!) modify 'TEST_STRING_JSON' // but its copy instead

       run_json_test(TEST_STRING_JSON);
   }

} </lsl> |caveats= |helpers |also_functions=|-style="vertical-align:top;" | style="color:gray;" |•  | llList2Json | style="color:gray;" | | | |-style="vertical-align:top;" | style="color:gray;" |•  | llJson2List | style="color:gray;" | | | |-style="vertical-align:top;" | style="color:gray;" |•  | llJsonGetValue | style="color:gray;" | | | |-style="vertical-align:top;" | style="color:gray;" |•  | llJsonValueType | style="color:gray;" | | | |also_events |also_tests |also_articles=|-style="vertical-align:top;" | style="color:gray;" |•  | Typecast | style="color:gray;" | | | |notes= |permission |negative_index |sort=JsonSetValue |cat1=List |cat2=String |cat3=Data Conversion |cat4=JSON |history = Date of Release 20/05/2013 }}