# Example 4 This example program demonstrates the basic structure of an RPG program utilizing RXS to compose a JSON string with repeating elements. ### Free Format EX4.rpgle ```rpgle **FREE Ctl-Opt ActGrp(*Caller) BndDir('RXSBND') Option(*NoDebugIO) ExtBinInt(*Yes) DecEdit('0.') Text('Ex. 4 - JSON Compose'); /COPY QRPGLECPY,RXSCB Dcl-Ds PutStmfDS LikeDS(RXS_PutStmfDS_t); Dcl-Ds CreateJsonDS LikeDS(RXS_CreateJsonDS_t); Dcl-Ds RootDS LikeDS(RXS_JsonStructureDS_t); Dcl-Ds UsersArrayDS LikeDS(RXS_JsonStructureDS_t); Dcl-Ds UserObjectDS LikeDS(RXS_JsonStructureDS_t); Dcl-Ds JsonArrayDS LikeDS(RXS_JsonStructureDS_t); Dcl-S i Uns(3); Dcl-S JSON Like(RXS_Var64Kv_t); Dcl-S dateVal Char(10); monitor; // Use RXS_ResetDS to ensure that the CreateJsonDS data structures is // properly initialized. We don't have to use this on the various // RXS_JsonStructureDS_t structures because the other RXS subprocedures // will handle those for us. RXS_ResetDS( CreateJsonDS : RXS_DS_TYPE_CREATEJSON ); // Create root JSON Object CreateJsonDS.Prettify = RXS_JSON_TRUE; CreateJsonDS.JsonStructureType = RXS_JSON_STRUCTURE_OBJECT; RootDS = RXS_CreateJson( CreateJsonDS ); // Create JSON Array named users & attach to RootDS UsersArrayDS = RXS_ComposeJsonArray( 'users' : RootDS ); // Loop through and add multiple objects to a JSON Array named "users". // Typically you'd want to use a normal RPG database read loop here // instead of a 'for' loop. for i = 1 to 3; // Create object for a customer, attach to array UserObjectDS = RXS_ComposeJsonObject( *Omit : UsersArrayDS ); // Add various character fields & data to the users object we just created. RXS_ComposeJsonString( 'firstName' : 'First Name' : UserObjectDS ); RXS_ComposeJsonString( 'lastName' : 'Last Name' : UserObjectDS ); RXS_ComposeJsonString( 'email' : 'Email Address' : UserObjectDS ); RXS_ComposeJsonString( 'username' : 'Username' : UserObjectDS ); RXS_ComposeJsonString( 'password' : 'Password' : UserObjectDS ); endfor; // The next few parts of this JSON structure are a series of arrays. // We could define D spec data structure for each if we wanted to, // but it's not required. We still need to ensure we're attaching // them to our root object RootDS though. JsonArrayDS = RXS_ComposeJsonArray( 'requiredCourseIds' : RootDS ); // Again, you'd probably be reading one or more child records out of // a physical file here with an RPG read loop instead of a 'for' loop. for i = 1 to 10; // Note that the key difference between a JSON Object and a // JSON Array is that a JSON Object can contain one or more // name/value pairs (and the values can be of any type - a child // JSON Object, a JSON Array, or just a plain string/int/etc value) // A JSON Array can hold one or more values ONLY. The values a JSON // Array holds must all be of the same type (e.g. all JSON Object, // all plain string/int/etc values, or even another JSON Array), // and cannot have a name associated with them. // The easiest way to think about these two is that a JSON Object // is like an RPG data structure, whereas a JSON Array is like // an RPG data structure or normal field but with the Dim keyword // used. // Because we can't name the values we're putting in our array, the // second parm for RXS_ComposeJsonNumber() must be *OMIT. // We're using RXS_ComposeJsonNumber() to ensure that in the JSON // the values we're passing show up as numeric (e.g. not wrapped // in double quotes) // To handle large numbers effectively, RXS_ComposeJsonNumber() // actually accepts a character representation of a number as // opposed to an RPG numeric field type. RXS_ComposeJsonNumber( *Omit : %Char(i) : JsonArrayDS ); endfor; // We're re-using the JsonArrayDS structure for the next few arrays // as they are very simple arrays but the whole process is otherwise // the same as for requiredCourseIds[] JsonArrayDS = RXS_ComposeJsonArray( 'courseIds' : RootDS ); for i = 1 to 10; RXS_ComposeJsonNumber( *Omit : %Char(i * 2) : JsonArrayDS ); endfor; JsonArrayDS = RXS_ComposeJsonArray( 'seriesIds' : RootDS ); for i = 1 to 10; RXS_ComposeJsonNumber( *Omit : %Char(i * 3) : JsonArrayDS ); endfor; JsonArrayDS = RXS_ComposeJsonArray( 'groupIds' : RootDS ); for i = 1 to 10; RXS_ComposeJsonNumber( *Omit : %Char(i * 4) : JsonArrayDS ); endfor; // Next, we need to add a date named datestamp to our RootDS. // JSON doesn't have a 'date' data type, so we add this as a // string and do whatever formatting the API we're calling requires. // In this case we're using *ISO YYYY-MM-DD date format dateVal = %Char( %Date() : *ISO ); RXS_ComposeJsonString( 'datestamp' : dateVal : RootDS ); // Next we're going to add JSON boolean and null values RXS_ComposeJsonBoolean( 'processed' : RXS_JSON_TRUE : RootDS ); RXS_ComposeJsonNull( 'referenceId' : RootDS ); // Now that we've added all of the data fields to our JSON object, // let's generate our JSON string JSON = RXS_GetJsonString( CreateJsonDS ); // Dump JSON to file RXS_ResetDS( PutStmfDS : RXS_DS_TYPE_PUTSTMF ); PutStmfDS.Stmf = '/tmp/json_excompose1.txt'; RXS_PutStmf( JSON : PutStmfDS ); on-error; RXS_DestroyJson( CreateJsonDS ); endmon; // Always call RXS_DestroyJson() to free up the memory we used. // This must be called AFTER we retrieve our string // with RXS_GetJsonString(), or there will be nothing to retrieve! // It is enough to just call RXS_DestroyJson() on the CreateJsonDS data // structure - it will free the memory used by all of the child // data structures that were linked to it as well. RXS_DestroyJson( CreateJsonDS ); *INLR = *ON; return; ``` ### Fixed Format FX_EX4.rpgle ```rpgle H DFTACTGRP(*NO) ACTGRP(*CALLER) BNDDIR('RXSBND') OPTION(*NODEBUGIO) H EXTBININT(*YES) DECEDIT('0.') H TEXT('Fixed Format Ex. 4 - JSON Compose') /COPY QRPGLECPY,RXSCB D PutStmfDS DS LikeDS(RXS_PutStmfDS_t) D CreateJsonDS DS LikeDS(RXS_CreateJsonDS_t) D RootDS DS LikeDS(RXS_JsonStructureDS_t) D UsersArrayDS DS LikeDS(RXS_JsonStructureDS_t) D UserObjectDS DS LikeDS(RXS_JsonStructureDS_t) D JsonArrayDS DS LikeDS(RXS_JsonStructureDS_t) D i S 3U 0 D JSON S Like(RXS_Var64Kv_t) D dateVal S 10A /FREE monitor; // Use RXS_ResetDS to ensure that the CreateJsonDS data structures is // properly initialized. We don't have to use this on the various // RXS_JsonStructureDS_t structures because the other RXS // subprocedures will handle those for us. RXS_ResetDS( CreateJsonDS : RXS_DS_TYPE_CREATEJSON ); // Create root JSON Object CreateJsonDS.Prettify = RXS_JSON_TRUE; CreateJsonDS.JsonStructureType = RXS_JSON_STRUCTURE_OBJECT; RootDS = RXS_CreateJson( CreateJsonDS ); // Create JSON Array named users & attach to RootDS UsersArrayDS = RXS_ComposeJsonArray( 'users' : RootDS ); // Loop through and add multiple objects to the JSON Array named // "users". Typically you'd want to use a normal RPG database // read loop here instead of a 'for' loop. for i = 1 to 3; // Create object for a customer, attach to array UserObjectDS = RXS_ComposeJsonObject( *Omit : UsersArrayDS ); // Add various character fields & data to the users object we just // created. RXS_ComposeJsonString( 'firstName' : 'First Name' : UserObjectDS ); RXS_ComposeJsonString( 'lastName' : 'Last Name' : UserObjectDS ); RXS_ComposeJsonString( 'email' : 'Email Address' : UserObjectDS ); RXS_ComposeJsonString( 'username' : 'Username' : UserObjectDS ); RXS_ComposeJsonString( 'password' : 'Password' : UserObjectDS ); endfor; // The next few parts of this JSON structure are a series of arrays. // We could define D spec data structure for each if we wanted to, // but it's not required. We still need to ensure we're attaching // them to our root object RootDS though. JsonArrayDS = RXS_ComposeJsonArray( 'requiredCourseIds' : RootDS ); // Again, you'd probably be reading one or more child records out of // a physical file here with an RPG read loop instead of a // 'for' loop. for i = 1 to 10; // Note that the key difference between a JSON Object and a // JSON Array is that a JSON Object can contain one or more // name/value pairs (and the values can be of any type - a child // JSON Object, a JSON Array, or just a plain string/int/etc value) // A JSON Array can hold one or more values ONLY. The values a JSON // Array holds must all be of the same type (e.g. all JSON Object, // all plain string/int/etc values, or even another JSON Array), // and cannot have a name associated with them. // The easiest way to think about these two is that a JSON Object // is like an RPG data structure, whereas a JSON Array is like // an RPG data structure or normal field but with the Dim keyword // used. // Because we can't name the values we're putting in our array, the // second parm for RXS_ComposeJsonNumber() must be *OMIT. // We're using RXS_ComposeJsonNumber() to ensure that in the JSON // the values we're passing show up as numeric (e.g. not wrapped // in double quotes) // To handle large numbers effectively, RXS_ComposeJsonNumber() // actually accepts a character representation of a number as // opposed to an RPG numeric field type. RXS_ComposeJsonNumber( *Omit : %Char(i) : JsonArrayDS ); endfor; // We're re-using the GenericArrayDS structure for the next few arrays // as they are very simple arrays but the whole process is otherwise // the same as for requiredCourseIds[] JsonArrayDS = RXS_ComposeJsonArray( 'courseIds' : RootDS ); for i = 1 to 10; RXS_ComposeJsonNumber( *Omit : %Char(i * 2) : JsonArrayDS ); endfor; JsonArrayDS = RXS_ComposeJsonArray( 'seriesIds' : RootDS ); for i = 1 to 10; RXS_ComposeJsonNumber( *Omit : %Char(i * 3) : JsonArrayDS ); endfor; JsonArrayDS = RXS_ComposeJsonArray( 'groupIds' : RootDS ); for i = 1 to 10; RXS_ComposeJsonNumber( *Omit : %Char(i * 4) : JsonArrayDS ); endfor; // Next, we need to add a date named datestamp to our RootDS. // JSON doesn't have a 'date' data type, so we add this as a // string and do whatever formatting the API we're calling requires. // In this case we're using a YYYY-MM-DD date format dateVal = %Char( %Date() : *ISO ); RXS_ComposeJsonString( 'datestamp' : dateVal : RootDS ); // Next we're going to add JSON boolean and null values RXS_ComposeJsonBoolean( 'processed' : RXS_JSON_TRUE : RootDS ); RXS_ComposeJsonNull( 'referenceId' : RootDS ); // Now that we've added all of the data fields to our JSON object, // let's generate our JSON string JSON = RXS_GetJsonString( CreateJsonDS ); // Dump JSON to file RXS_ResetDS( PutStmfDS : RXS_DS_TYPE_PUTSTMF ); PutStmfDS.Stmf = '/tmp/json_excompose1.txt'; RXS_PutStmf( JSON : PutStmfDS ); on-error; RXS_DestroyJson( CreateJsonDS ); endmon; // Always call RXS_DestroyJson() to free up the memory we used. // This must be called AFTER we retrieve our string // with RXS_GetJsonString(), or there will be nothing to retrieve! // It is enough to just call RXS_DestroyJson() on the CreateJsonDS data // structure - it will free the memory used by all of the child // data structures that were linked to it as well. RXS_DestroyJson( CreateJsonDS ); *INLR = *ON; return; /END-FREE ```