June 2


RPG Example reading JSON using YAJL from IFS

By NickLitten

June 2, 2017

#RPG, #FREE, #ILE, #JSON, #prettydarnquick, #RPGLE, #snippet, #SQL, #YAJL

Decode JSON webservice reply data (already stored in IFS) using YAJL

This reads 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:

{{ "users": [{ "userID": "@123", "firstName": "Billy", "lastName": "Bob", "initials": "123",
 "company": 110, "division": 30, "department": 325, "secProfile": "" }, { "userID": "AAATEMP",
 "firstName": "Albert", "lastName": "Smith", "initials": "AAA", "company": 110, "division": 1,
 "department": 1, "secProfile": "" }, { "userID": "AAATEST", "firstName": "Andy",
 "lastName": "Tester", "initials": "AAA", "company": 110, "division": 1, "department": 530,
 "secProfile": "AAT" }, { "userID": "AAA3", "firstName": "Fred", "lastName": "Blogs",
 "initials": "AA3", "company": 110, "division": 1, "department": 1, "secProfile": "AAA" },
 { "userID": "AATEST", "firstName": "AA", "lastName": "TEST", "initials": "AAT", "company": 110,
 "division": 1, "department": 1, "secProfile": "" }, { "userID": "ABB", "firstName": "Abba",
 "lastName": "Dancing Queen", "initials": "", "company": 110, "division": 1, "department": 1,
 "secProfile": "" }, { "userID": "BINGBONG", "firstName": "Bing", "lastName": "Bong",
 "initials": "BB", "company": 110, "division": 2, "department": 2, "secProfile": "" },
 { "userID": "LITTENN", "firstName": "Nick", "lastName": "Litten", "initials": "NJL",
 "company": 1, "division": 1, "department": 123, "secProfile": "Secret Squirrel" }]}

This JSON example contains the values:

USERID varchar(100); 
 FIRSTNAME varchar(100); 
 LASTNAME varchar(100); 
 INITIALS varchar(100); 
 COMPANY int(10); 
 DIVISION int(10); 
 DEPARTMENT int(10);

So. lets read it and break it out into fields, which I am just storing in an array. You could write them to a file just as easily…

**FREE /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('/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:' + %char(%diff(endTimeStamp:strJsonTimeStamp:*mseconds)) ; // stick that message into the joblog so we can clearly see the runtime QMHSNDPM( 'CPF9897' : 'QCPFMSG *LIBL' : joblogMsg : %len(%trimr(joblogMsg)) : '*DIAG' : '*' : 0 : MsgKey : ErrorCode ); else; // If unable to load JSON data from the IFS then tell the world result.success = *off; result.errmsg = 'Bugger! I couldnt read the IFS file'; endif; *inlr = *on;

So what does this do?

(1) reads the JSON from the input IFS File

(2) Stores a timestamp

(3) decodes the JSON and stores all the values in an array

(4) sends a message to the joblog saying how long it took.

In this case :

JSNIFSYAJL Completed with 91 elements. Total runtime:11000 YAJL DECODE


Let’s look at some examples

  • This doesn’t find anything… list = YAJL_object_find(docNode: ‘users’); Mine isn’t “users” but _source is my node. It doesn’t find it or any other one I try to use. They are all in the json file.

  • {"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}

    Join the IBM i Community for FREE Presentations, Lessons, Hints and Tips