EXCOMPOSE1

This example program demonstrates the basic structure of an RPG program utilizing RPG-XML Suite to compose a JSON string with repeating elements.


H DFTACTGRP(*NO) ACTGRP(*CALLER) BNDDIR('RXSBND')
 /copy QRPGLECPY,RXSCB
D PutStmfDS       DS                  LikeDS(RXS_PutStmfDS_t)
D CreateDS        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 GenericArrayDS  DS                  LikeDS(RXS_JsonStructureDS_t)
D i               S              3U 0 Inz(0)
D Json            S                   Like(RXS_Var64Kv_t)
D dateVal         S             10A
 /FREE

  monitor;

    // Use RXS_ResetDS to ensure that RXS templated data structures are 
    //  properly configured
    RXS_ResetDS( CreateDS : RXS_DS_TYPE_CREATEJSON );
    RXS_ResetDS( RootDS : RXS_DS_TYPE_JSONSTRUCTURE );
    RXS_ResetDS( UsersArrayDS : RXS_DS_TYPE_JSONSTRUCTURE );
    RXS_ResetDS( UserObjectDS : RXS_DS_TYPE_JSONSTRUCTURE );
    RXS_ResetDS( GenericArrayDS : RXS_DS_TYPE_JSONSTRUCTURE );

    // Create root JSON Object
    CreateDS.Prettify = RXS_JSON_TRUE;
    CreateDS.JsonStructureType = RXS_JSON_STRUCTURE_OBJECT;
    RootDS = RXS_CreateJson( CreateDS );

    // 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 specific string fields & data to the User 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.
    // requiredCourseIds[] - Mindflash says optional
    GenericArrayDS =
      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) : GenericArrayDS );

    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[]
    GenericArrayDS = RXS_ComposeJsonArray( 'courseIds' : RootDS );

    for i = 1 to 10;
      RXS_ComposeJsonNumber( *OMIT : %Char(i * 2) : GenericArrayDS );
    endfor;

    GenericArrayDS = RXS_ComposeJsonArray( 'seriesIds' : RootDS );

    for i = 1 to 10;
      RXS_ComposeJsonNumber( *OMIT : %Char(i * 3) : GenericArrayDS );
    endfor;

    GenericArrayDS = RXS_ComposeJsonArray( 'groupIds' : RootDS );

    for i = 1 to 10;
      RXS_ComposeJsonNumber( *OMIT : %Char(i * 4) : GenericArrayDS );
    endfor;

    // Next, we need to add a date named clientDatestamp 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( CreateDS );
    
    // Always call RXS_JsonDestroy() to free up the memory we used.
    // This must be called AFTER we retrieve our string0
    //  with RXS_JsonGetString(), or there will be nothing to retrieve!
    // It is enough to just call RXS_JsonDestroy() on the CreateDS data
    //  structure - it will free the memory used by all of the child
    //  data structures that were linked to it as well.
    RXS_DestroyJson( CreateDS );
    
    // 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( CreateDS );
  
  endmon;
  
  RXS_DestroyJson( CreateDS );
  
  *INLR = *ON;
  
  return;
  
 /END-FREE