RPG Example to Read JSON and Decode
Let's use an opensource software tool called YAJL to read the response we just got from our webservice. This response was stored in the IFS for this example.
This code example takes the JSON from the IFS – decodes it using Y.A.J.L and reports on time taken to perform decode.
Writing an RPG program to read JSON using YAJL is actually pretty straightforward — I hope this code example helps!
In this case the JSON data is a simple layout that looks like this:
This JSON example contains the values:
FIRSTNAME varchar(100);
LASTNAME varchar(100);
INITIALS varchar(100);
COMPANY int(10);
DIVISION int(10);
DEPARTMENT int(10);
Lets read it and break it out into fields. Then I am just storing these data fields in an array. You could write them to a file just as easily…
/TITLE JSON_TABLE Decode JSON using Y.A.J.L. - Proof of Concept
// ------------------------------------------------------
// PROGRAM CREATION OVERRIDES:
//
// Create as a Module and bind into ILE program
//
// JSNIFSYAJL.sqlrpgle (fully /free)
//
// This demonstrates reading JSON data from an IFS file and then
// parsing that JSON to break out the subffields using Y.A.J.L.
// Subfields within the objects are retrieved by their field names.
//
// The JSON data is loaded into a data structure suitable
// for display from a program debugger.
//
// Compile - ADDLIBLE : LITTENN LMDTA06NL YAJL
//
// Check input data -
// DSPLNK OBJ( ** value from IFSFilename ** )
//
// MODIFICATION HISTORY:
//
// 07/17/2017 nick.litten V1.00
//
ctl-opt dftactgrp(*no) actgrp('LITTENN')
option(*nodebugio:*srcstmt:*nounref)
bnddir('YAJL') alwnull(*inputonly)
datfmt(*ISO) decedit('0.')
copyright('| JSNIFSYAJL 1.0 06/27/2017 Use YAJL to read JSON from IFS and Parse.');
/include yajl_h
// IFS file with JSON code that we will be reading and decoding
dcl-c ifsFilename
const('/home/littenn/getwebjsn.json');
dcl-ds jsonFields qualified template;
USERID varchar(100);
FIRSTNAME varchar(100);
LASTNAME varchar(100);
INITIALS varchar(100);
COMPANY int(10);
DIVISION int(10);
DEPARTMENT int(10);
end-ds;
dcl-ds result qualified;
success ind;
errmsg varchar(500);
jsonArray likeds(jsonFields) dim(9999);
end-ds;
dcl-s docNode like(yajl_val);
dcl-s list like(yajl_val);
dcl-s node like(yajl_val);
dcl-s val like(yajl_val);
dcl-s Count int(10);
dcl-s lastElement int(10) inz;
dcl-s errMsg varchar(500) inz('');
dcl-s strTimeStamp timestamp inz; // start of pgm
dcl-s strJsonTimeStamp timestamp inz; // start of JSON decode logic
dcl-s endTimeStamp timestamp inz; // used to calculate duration
// Parms for logging-text being sent back into program message queue
dcl-pr QMHSNDPM extpgm('QMHSNDPM');
*n char(7) const; // MsgID
*n char(20) const; // MsgFile
*n char(32767) const options(*varsize); // MsgData
*n int(10) const; // MsgDtaLen
*n char(10) const; // MsgType
*n char(10) const; // StackEntry
*n int(10) const; // StackCount
*n char(4); // MsgKey
*n char(32767) options(*varsize); // ErrorCode
end-pr;
dcl-ds ErrorCode;
BytesProv int(10) inz(0);
BytesAvail int(10) inz(0);
end-ds;
dcl-s joblogMsg char(200);
dcl-s MsgKey char(4);
/Title [---------- MAINLINE ---------- ]
strTimeStamp=%timestamp();
// Load JSON in from the IFS file using YAJL
docNode = yajl_stmf_load_tree( ifsFilename : errMsg );
// If it loaded then lets decode it:
if errMsg = '';
strJsonTimeStamp=%timestamp();
// Write the JSON *header* level values
node = YAJL_object_find(docNode: 'success');
result.success = YAJL_is_true(node);
node = YAJL_object_find(docNode: 'errmsg');
result.errmsg = YAJL_get_string(node);
list = YAJL_object_find(docNode: 'users');
// Write the JSON *data array* level values
Count = 0;
dow YAJL_ARRAY_LOOP( list: Count: node );
lastElement = Count;
val = YAJL_object_find(node: 'userID');
result.jsonArray(Count).userID = yajl_get_string(val);
val = YAJL_object_find(node: 'firstName');
result.jsonArray(Count).firstName = yajl_get_string(val);
val = YAJL_object_find(node: 'lastName');
result.jsonArray(Count).lastName = yajl_get_string(val);
val = YAJL_object_find(node: 'initials');
result.jsonArray(Count).initials = yajl_get_string(val);
val = YAJL_object_find(node: 'company');
result.jsonArray(Count).company = yajl_get_number(val);
val = YAJL_object_find(node: 'division');
result.jsonArray(Count).division = yajl_get_number(val);
val = YAJL_object_find(node: 'department');
result.jsonArray(Count).department = yajl_get_number(val);
enddo;
yajl_tree_free(docNode);
// Set Ending timestamps and calculate runtime
endTimeStamp=%timestamp();
joblogMsg = 'JSNIFSYAJL Completed with ' +
%char(lastElement) +
' elements. Total runtime:' +
%char(%diff(endTimeStamp:strTimeStamp:*mseconds)) +
' YAJL DECODE only:' +
// stick that message into the joblog so we
QMHSNDPM( 'CPF9897'
: 'QCPFMSG *LIBL'
: joblogMsg
: %len(%trimr(joblogMsg))
: '*DIAG'
: '*'
: 0
: MsgKey
: ErrorCode );
else;
// If unable to load JSON data from the IFS then
result.success = *off;
result.errmsg = 'Aaargh! I couldnt read the IFS file';
endif;
*inlr = *on;
So what does this do?
In this case :
Easy Peasy right?