JSONPUTVALUE Function

Purpose

Adds a value, as UTF-8, to a JSON text.

Syntax

JSONPUTVALUE(p,l[,v])

Parameters

p
A pointer specifying the address of the JSON text buffer.
l
Specifies the length in bytes of the JSON text buffer.
v
A reference to a PL/I variable, which may be scalar, array, or a structure or a combination. If it is a structure, it must not contain any elements that have * names, have UNION or GRAPHIC attributes, are scaled FIXED BINARY, or are FIXED DECIMAL (p, q) where q < 0 or q > p.

Description

JSONPUTVALUE encodes the value (value of name-value pair) to UTF-8 and writes it to the buffer if there is sufficient space. If successful, it returns the number of bytes written. For a description of what a value is, see JSONGETVALUE.

The ERROR condition is raised if the JSON text buffer has insufficient space to accommodate the member. The ONCODE built-in function tells you why the ERROR condition was raised and the ONSUBCODE built-in function will indicate the number of bytes that were written. The number of bytes actually written will be <= l (second argument).

Examples

For a complete program using various JSON built-in functions, see the last example under JSONPUTVALUE.

Example 1:

Suppose Dcl Array(5) fixed bin(31) init(1, 2, 3, 4, 5);, then bytes = jsonputvalue (bufp, bufl, Array);

will have the following UTF-8 text at the beginning of the buffer: [1,2,3,4,5] (no spaces).

Example 2:

Suppose Dcl Towns fixed bin(31) init(6);, then bytes = jsonputvalue(bufp, bufl, Towns); will have the following UTF-8 text at the beginning of the buffer: 6

Example 3:

Suppose

dcl 1 S3,
       2 fd(2),
         3 d2 fixed bin(15) init(2, 4),
         3 d5 fixed dec(7) init(5, 9);

then bytes = jsonputvalue (bufp, bufl, Array); will have the following UTF-8 text at the beginning of the buffer: {"FD":[{"D2":2,"D5":5},{"D2":4,"D5":9}]}.

Example 4:

Using the full program in example 5 below, you will see that:

  • The get_n_list procedure reads an adjustable structure (with the REFER option) where the number of Towns can be any number and the same code is capable of reading the whole object.
  • The put procedure recreates the object just read piecemeal using various JSON built-in functions. The newly created object is re-read using get_n_list, allocating a new structure.
  • The newly created and re-read object is effectively the same as the original. This object is then re-created using just one JSON built-in function invocation, specifically, bytes = jsonputvalue(bufp, buf_size, Unusual_Town_Names);
  • This newly created object is then re-read using just one JSON built-in function invocation, specifically, bytes = jsonputmember(bufp, buf_size, Unusual_Town_Names);

Example 5:

The sample below is for illustrative purposes only. You will find the actual source code in the src folder in the product install directory.

package: package exports(*);
 zzyzx: proc options(main);
 %replace buf_size by 500;
 dcl txt                             char(120) var;
 dcl (Towns, bufl, bytes, ix)        fixed bin(31);
 dcl (bufp, Unusual_Town_Names_ptr)  ptr;
 dcl (buf, bufe)                     char(buf_size) var;
 dcl err                             char(20);
 dcl charvar_len                     fixed bin(15) based;
 dcl 1 * union static,
       3 *                           fixed bin(15) init(1),
       3 *,
         5 *                         char,
         5 big                       char;
 dcl 1 Unusual_Town_Names            based(Unusual_Town_Names_ptr),
       3 No_of_Towns                 fixed bin(31),
       3 Details(Towns refer(No_of_Towns)),
         5 No                        fixed bin(31),
         5 Name                      char(30) varying,
         5 Place                     char(30) varying,
         5 Really                    bit;

 on error
   begin;
     on error system;
     put skip list('Bytes read=' || bytes, ' oncode=' ||
           trim(oncode()) || ' onsubcode=' || trim(onsubcode()));
     if onsubcode() ^= 0 then
       do;
         put skip list('JSON object invalid at pos ' ||
                        trim(onsubcode));
         put skip list('<V---+----10---+----2>');
         err = substr(buf, onsubcode());
         if 'a' = 'a'e then
           call pliebcdic(addr(err), addr(err), length(err));
         put skip list('<' || err || '>');
       end;
     put skip list('bufl=', length(buf));
   end;

 if 'a'  = 'a'e  then put skip list('Running EBCDIC,');
                 else put skip list('Running ASCII,');
 if big ^= '00'x then    put list(' Bigendian.');
                 else    put list(' Littleendian.');
 bufe =
 '{ "Towns": 6,
    "Details" :
    [
     { "No": 1, "Name": "Accident","Place": "Maryland", "Really":true},
     { "No": 2, "Name": "Boring",  "Place": "Oregon",  "Really": true},
     { "No": 3, "Name": "Dull",    "Place": "Scotland","Really": true},
     { "No": 4, "Name": "Noplace", "Place": "England","Really": false},
     { "No": 5, "Name": "Why",     "Place": "Arizona", "Really": true},
     { "No": 6, "Name": "Zzyzx",   "Place":"California","Really":true}
    ]
   }';
 buf   = utf8(bufe);
 bufp  = addrdata(buf);
 bufl  = length(buf);
 bytes = jsonvalid(bufp, bufl);
 if bytes ^= 0 then
   do;
     put skip list("Original JSON invalid at pos " || trim(bytes));
     put skip list('<V---+----10---+----2>');
     err = substr(buf, bytes);
     put skip list('<' || err || '>');
   end;
 else
   put skip list("Original JSON object is valid.");

 /*===================================================================*/
 /* Let's read the JSON object and populate Unusual_Town_Names        */
 /* structure, then create the JSON object again. After "call put",   */
 /* newly created JSON object should have exectaly the same content   */
 /* as the original except that all blanks will have been removed     */
 /*===================================================================*/
 call get_n_list;

 put skip list((70)'*');
 put skip list('Using BUILTINs jsonput/get functions ...');
 call put;

 bytes = jsonvalid(bufp, bufl);
 if bytes ^= 0 then
   do;
     put skip list("Newly created JSON invalid at pos " || trim(bytes));
     put skip list('<V---+----10---+----2>');
     err = substr(buf, bytes);
     if 'a' = 'a'e then
       call pliebcdic(addr(err), addr(err), length(err));
     put skip list('<' || err || '>');
   end;
 else
   put skip list("Newly created JSON object is valid.");

 /*===================================================================*/
 /* If all goes well, we should be able ot read it again              */
 /*===================================================================*/
 call get_n_list;

 /*===================================================================*/
 /* We can re-create the entire object with just BUILTIN invocation   */
 /*===================================================================*/
 put skip list((70)'*');
 put skip list('Using BUILTINs jsonput/get VALUE ...');
 bytes = jsonputvalue(bufp, buf_size, Unusual_Town_Names);
 addr(buf)->charvar_len = bytes;
 bufl  = length(buf);
 put skip list('Bytes Written=' || trim(bytes));
 /*===================================================================*/
 /* ... read the entire object with just one BUILTIN invocation       */
 /*===================================================================*/
 bytes = jsongetvalue(bufp, bufl, Unusual_Town_Names);
 put skip;
 put skip list('Bytes Read=' || trim(bytes) ||
               ' Buffer Length=' || trim(bufl));

 /*===================================================================*/
 /* We can re-create the entire object with just BUILTIN invocation   */
 /* but with inclusion of the top lebel name                          */
 /*===================================================================*/
 put skip list((70)'*');
 put skip list('Using BUILTINs jsonput/get MEMBER ...');
 bytes = jsonputmember(bufp, buf_size, Unusual_Town_Names);
 addr(buf)->charvar_len = bytes;
 bufl  = length(buf);
 put skip list('Bytes Written=' || trim(bytes));
 /*===================================================================*/
 /* ... read the entire object with just one BUILTIN invocation       */
 /* but with inclusion of the top lebel name                          */
 /*===================================================================*/
 bytes = jsongetmember(bufp, bufl, Unusual_Town_Names);
 put skip;
 put skip list('Bytes Read=' || trim(bytes) ||
               ' Buffer Length=' || trim(bufl));

 put skip list((70)'*');
 put skip list('Done with the tests.');

 /*===================================================================*/
 get_n_list:proc;
   bytes  = jsongetobjectstart(bufp,       bufl        );
   bytes += jsongetmember(bufp + bytes,    bufl - bytes, Towns);
   allocate Unusual_Town_Names;
   bytes += jsongetcomma (bufp + bytes,    bufl - bytes);
   bytes += jsongetmember(bufp + bytes,    bufl - bytes, Details);
   bytes += jsongetobjectend(bufp + bytes, bufl - bytes);
   do ix = 1 to towns;
     txt = trim(no(ix)) || ' is ' || name(ix)  || ', ' ||
                                     place(ix) || '. ';
     if really(ix) then
       txt ||= "Yes it's true.";
     else
       txt ||= "It's false!.";
     put skip list(txt);
   end;
   put skip;
   put skip list('Bytes Read=' || trim(bytes) ||
                 ' Buffer Length=' || trim(bufl));
 end get_n_list;

 /*===================================================================*/
 put:proc;
   bytes  = jsonputobjectstart(bufp,    buf_size              );
   bytes += jsonputmember(bufp + bytes, buf_size - bytes, Towns);
   bytes += jsonputcomma(bufp + bytes, buf_size - bytes);
   bytes += jsonputmember(bufp + bytes, buf_size - bytes, Details);
   bytes += jsonputobjectend(bufp + bytes, buf_size - bytes);
   addr(buf)->charvar_len = bytes;
   bufl  = length(buf);
   put skip list('Bytes Written=' || trim(bytes));
   put skip;
 end put;

 end zzyzx;
 end package;

Restrictions

None.