Forums >> Programming >> Proof of Concept (POC)

Jump to:




bvstone

Parsing JSON using RPG with Scott Klement's Port of YAJL (Yet Another JSON Library) - Part 3

Posted:

Parsing JSON using RPG with Scott Klement's Port of YAJL (Yet Another JSON Library) - Part 3

In my dealings with JSON I found that most JSON structures are created as one large object.  This means they start with a { bracket and end with a } bracket.

But, I have seen cases where the JSON data itself is an array of objects.  This means the data starts with [ and ends with ].  While I've never understood why this was allowed, I'm in no place to question it.  But I just feel that it would be just as easy to wrap the entire array in one more object.

Here is some sample JSON data where the data itself is an array of objects:

[  
      {  
         "id":352104,
         "vin":"123456",
         "label":"3070",
         "color":"WHITE",
         "make":"VOLVO",
         "model":"VN",
         "deviceSerialNumber":"5010395849",
         "year":2005,
         "odometer":{  
            "units":"MILES",
            "timestamp":"2014-10-14T18:37:13Z",
            "readOnly":"TRUE",
            "value":199400.38
         },
         "engineRunTime":{  
            "isTracked":"ALWAYS",
            "timestamp":"2014-10-14T18:33:49Z",
            "readOnly":"TRUE",
            "value":"P478DT6H24M0.000S"
         },
         "licensePlate":{  
            "state":"FL",
            "country":"US"
         },
         "trackableItemType":"VEHICLE",
         "fuelType":"DIESEL",
         "createdTimestamp":{  
            "readOnly":true,
            "value":"2013-11-15T16:43:47Z"
         },
         "modifiedTimestamp":{  
            "readOnly":true,
            "value":"2014-10-10T19:11:50Z"
         }
      },
      {  
         "id":354261,
         "vin":"234567",
         "label":"3292",
         "color":"WHITE",
         "make":"VOLVO",
         "model":"VN",
         "deviceSerialNumber":"5010411594",
         "year":2011,
         "odometer":{  
            "units":"MILES",
            "timestamp":"2014-10-14T18:38:14Z",
            "readOnly":"TRUE",
            "value":366985.99
         },
         "engineRunTime":{  
            "isTracked":"ALWAYS",
            "timestamp":"2014-10-14T18:18:11Z",
            "readOnly":"TRUE",
            "value":"P299DT19H0M0.000S"
         },
         "licensePlate":{  
            "state":"FL",
            "country":"US"
         },
         "trackableItemType":"VEHICLE",
         "fuelType":"DIESEL",
         "createdTimestamp":{  
            "readOnly":true,
            "value":"2013-11-22T18:30:51Z"
         },
         "modifiedTimestamp":{  
            "readOnly":true,
            "value":"2014-10-10T15:22:25Z"
         }
      },
      {  
         "id":356045,
         "vin":"345678",
         "label":"401",
         "color":"WHITE",
         "make":"MACK",
         "model":"CH",
         "deviceSerialNumber":"5010551993",
         "year":2001,
         "odometer":{  
            "units":"MILES",
            "timestamp":"2014-06-03T16:56:49Z",
            "readOnly":"TRUE",
            "value":203119.47
         },
         "engineRunTime":{  
            "isTracked":"ALWAYS",
            "timestamp":"2014-06-03T15:52:39Z",
            "readOnly":"TRUE",
            "value":"P229DT1H24M0.000S"
         },
         "licensePlate":{  
            "state":"FL",
            "country":"US"
         },
         "trackableItemType":"VEHICLE",
         "fuelType":"DIESEL",
         "createdTimestamp":{  
            "readOnly":true,
            "value":"2013-12-02T18:19:00Z"
         },
         "modifiedTimestamp":{  
            "readOnly":true,
            "value":"2014-10-10T17:11:55Z"
         }
      },
      {  
         "id":352049,
         "vin":"456789",
         "label":"3035",
         "color":"WHITE",
         "make":"VOVLO",
         "model":"VN430",
         "deviceSerialNumber":"5010404824",
         "year":2006,
         "odometer":{  
            "units":"MILES",
            "timestamp":"2014-10-14T18:38:11Z",
            "readOnly":"TRUE",
            "value":347126.47
         },
         "engineRunTime":{  
            "isTracked":"ALWAYS",
            "timestamp":"2014-10-14T18:13:48Z",
            "readOnly":"TRUE",
            "value":"P623DT6H12M0.000S"
         },
         "licensePlate":{  
            "state":"FL",
            "country":"US",
            "value":"084NLI"
         },
         "trackableItemType":"VEHICLE",
         "fuelType":"DIESEL",
         "createdTimestamp":{  
            "readOnly":true,
            "value":"2013-11-15T15:21:15Z"
         },
         "modifiedTimestamp":{  
            "readOnly":true,
            "value":"2013-11-15T15:21:15Z"
         }
      },
      {  
         "id":359172,
         "vin":"567890",
         "label":"3281",
         "color":"WHITE",
         "make":"VOLVO",
         "model":"VN",
         "deviceSerialNumber":"5010555410",
         "year":2011,
         "odometer":{  
            "units":"MILES",
            "timestamp":"2014-10-13T14:58:33Z",
            "readOnly":"TRUE",
            "value":360237.9
         },
         "engineRunTime":{  
            "isTracked":"ALWAYS",
            "timestamp":"2014-10-13T12:14:37Z",
            "readOnly":"TRUE",
            "value":"P316DT7H24M0.000S"
         },
         "licensePlate":{  
            "state":"FL",
            "country":"US"
         },
         "trackableItemType":"VEHICLE",
         "fuelType":"DIESEL",
         "createdTimestamp":{  
            "readOnly":true,
            "value":"2013-12-19T16:15:48Z"
         },
         "modifiedTimestamp":{  
            "readOnly":true,
            "value":"2014-10-10T15:21:15Z"
         }
      },
      {  
         "id":361056,
         "vin":"678901",
         "label":"3272",
         "color":"WHITE",
         "make":"WHITE",
         "model":"VN",
         "deviceSerialNumber":"5010587534",
         "year":2011,
         "odometer":{  
            "units":"MILES",
            "timestamp":"2014-10-10T19:27:39Z",
            "readOnly":"TRUE",
            "value":528542.0900000001
         },
         "engineRunTime":{  
            "isTracked":"ALWAYS",
            "timestamp":"2014-10-10T19:25:20Z",
            "readOnly":"TRUE",
            "value":"P300DT20H12M0.000S"
         },
         "licensePlate":{  
            "state":"FL",
            "country":"US"
         },
         "trackableItemType":"VEHICLE",
         "fuelType":"DIESEL",
         "createdTimestamp":{  
            "readOnly":true,
            "value":"2013-12-31T13:14:03Z"
         },
         "modifiedTimestamp":{  
            "readOnly":true,
            "value":"2014-10-10T15:18:36Z"
         }
      }
 ]

In these special cases the processing of the data is a little different.  We put together the following program as an example of processing this type of data:

     H DFTACTGRP(*NO) BNDDIR('YAJL')
      ****************************************************************
      * Imports
      ****************************************************************
      /include yajl_h
      ****************************************************************
      * Global Definitions
      ****************************************************************
     D CSTMSTDS      E DS                  EXTNAME(CSTMSTPF)
      ****************************************************************
      * Work Variables
      ****************************************************************
     D docNode         s                   like(yajl_val)
     D vehicleList     s                   like(yajl_val)
     D node            s                   like(yajl_val)
     D subNode         s                   like(yajl_val)
     D val             s                   like(yajl_val)
      *
     D stringValue     s          65535a   varying
     D decValue        s             13p 2
     D intValue        s             10i 0
      *
     D i               s             10i 0
     D errMsg          s            500a   varying inz('')
      ****************************************************************
      /free

       docNode = yajl_stmf_load_tree( '/tmp/jsonarray.json' : errMsg );

       if errMsg <> '';
          // handle error
       endif;

       exsr $Vehicles;

       yajl_tree_free(docNode);

       *inlr = *on;
       //***************************************************************
       //* Process Vehicles
       //***************************************************************
       begsr $Vehicles;

         vehicleList = docNode;

         i = 0;

         dow YAJL_ARRAY_LOOP(vehicleList:i:node );
            val = YAJL_object_find(node:'id');
            intValue = yajl_get_number(val);

            val = YAJL_object_find(node:'vin');
            stringValue = yajl_get_string(val);

            subNode = YAJL_object_find(node:'odometer');

            val = YAJL_object_find(subNode:'units');
            stringValue = yajl_get_string(val);

            val = YAJL_object_find(subNode:'value');
            decValue = yajl_get_number(val);

            subNode = YAJL_object_find(node:'engineRunTime');

            val = YAJL_object_find(subNode:'value');
            stringValue = yajl_get_string(val);

         enddo;

       endsr;

The first thing you'll probably notice is that to begin processing after loading the document we set the vehicleList pointer to the docNode pointer.  Why?  Well, because the entire set of JSON data itself is an array.

Once this is done we're able to use the YAJL_ARRAY_LOOP() function as before to process each item in the array.

Another difference in this example is that some of the item descriptions are objects themselves.

Take a look at the odometer object:

"odometer":{  
            "units":"MILES",
            "timestamp":"2014-10-14T18:37:13Z",
            "readOnly":"TRUE",
            "value":199400.38
         }

In order to process this we will need to get a pointer to the odometer object.  Luckily, we can find this just as easily as finding basic data.  We just use that pointer then to get values for each of the subfields:

            subNode = YAJL_object_find(node:'odometer');

            val = YAJL_object_find(subNode:'units');
            stringValue = yajl_get_string(val);

            val = YAJL_object_find(subNode:'value');
            decValue = yajl_get_number(val);

So, first we find the odometer object using the YAJL_object_find() procedure.  But, in this case we are saving the location in a pointer named subNode.  This pointer then points to the odometer object and we are able to retrieve the data items for this object.

We perform a similar action for retrieving the engineRunTime data.

Again, it isn't that difficult as long as you can keep track of what is pointing to what.  

Related Articles:


Last edited 07/12/2019 at 10:53:06



nkunde

RE: Parsing JSON using RPG with Scott Klement's Port of YAJL (Yet Another JSON Library) - Part 3

Posted:

RE: Parsing JSON using RPG with Scott Klement's Port of YAJL (Yet Another JSON Library) - Part 3

I tried using this example in a program but I can't seem to get it to work.

This is the JSON file

[{"serviceName":"USPS Priority Mail - Package","serviceCode":"usps_priority_mail","shipmentCost":8.7200,"otherCost":0.0},
{"serviceName":"USPS Priority Mail - Medium Flat Rate Box","serviceCode":"usps_priority_mail","shipmentCost":13.7500,"otherCost":0.0},
{"serviceName":"USPS Priority Mail - Small Flat Rate Box","serviceCode":"usps_priority_mail","shipmentCost":7.9000,"otherCost":0.0},
{"serviceName":"USPS Priority Mail - Large Flat Rate Box","serviceCode":"usps_priority_mail","shipmentCost":19.3000,"otherCost":0.0},
{"serviceName":"USPS Priority Mail - Flat Rate Envelope","serviceCode":"usps_priority_mail","shipmentCost":7.4000,"otherCost":0.0},
{"serviceName":"USPS Priority Mail - Flat Rate Padded Envelope","serviceCode":"usps_priority_mail","shipmentCost":8.0000,"otherCost":0.0},
{"serviceName":"USPS Priority Mail - Regional Rate Box A","serviceCode":"usps_priority_mail","shipmentCost":8.3400,"otherCost":0.0},
{"serviceName":"USPS Priority Mail - Regional Rate Box B","serviceCode":"usps_priority_mail","shipmentCost":9.5600,"otherCost":0.0},
{"serviceName":"USPS Priority Mail - Legal Flat Rate Envelope","serviceCode":"usps_priority_mail","shipmentCost":7.7000,"otherCost":0.0},
{"serviceName":"USPS Parcel Select Ground - Package","serviceCode":"usps_parcel_select","shipmentCost":8.4700,"otherCost":0.0}]

This is my code:

    D docNode         s                   like(yajl_val)
     D list            s                   like(yajl_val)
     D node            s                   like(yajl_val)
     D val             s                   like(yajl_val)

     D stringValue     s            500A   varying
     D decValue4       s             13P 4                     
     D decValue2       s             13P 2     

 

   list = docNode;

       // read results file
         i = 0;
         dow YAJL_ARRAY_LOOP( list: i: node );

           val = YAJL_object_find(node: 'serviceName');
           stringValue = yajl_get_string(val);
           sern14 = stringValue;

           val = YAJL_object_find(node: 'serviceCode');
           stringValue = yajl_get_string(val);
           serc14 = stringValue;

           val = YAJL_object_find(node: 'shipmentCost');
           decValue4 = yajl_get_number(val);
           cost14 = decValue4;

           val = YAJL_object_find(node: 'otherCost');
           decValue2 = yajl_get_number(val);
           cost14 =+ decValue2;                

 

What am I missing?

Thanks for your help

Nancy

      


Last edited 02/25/2021 at 07:53:26



bvstone

RE: Parsing JSON using RPG with Scott Klement's Port of YAJL (Yet Another JSON Library) - Part 3

Posted:

RE: Parsing JSON using RPG with Scott Klement's Port of YAJL (Yet Another JSON Library) - Part 3

I don't see where you're loading the JSON and setting docNode.


Last edited 02/25/2021 at 08:13:52



nkunde

RE: RE: Parsing JSON using RPG with Scott Klement's Port of YAJL (Yet Another JSON Library) - Part 3

Posted:

RE: RE: Parsing JSON using RPG with Scott Klement's Port of YAJL (Yet Another JSON Library) - Part 3

That was it.    I knew I had missed something but couldn't see it.

 

Thanks

Nancy


Last edited 02/25/2021 at 08:40:00



freppa73@gmail.com

RE: Parsing JSON using RPG with Scott Klement's Port of YAJL (Yet Another JSON Library) - Part 3

Posted:

RE: Parsing JSON using RPG with Scott Klement's Port of YAJL (Yet Another JSON Library) - Part 3

If you have an array in the array which node should you use to read the child array and how do you get it?


Last edited 12/08/2023 at 08:43:27



bvstone

RE: Parsing JSON using RPG with Scott Klement's Port of YAJL (Yet Another JSON Library) - Part 3

Posted:

RE: Parsing JSON using RPG with Scott Klement's Port of YAJL (Yet Another JSON Library) - Part 3

I like to create a new node for each array, especially in those cases.

 

arrayOne = YAJL_object_find(docNode:'arrayOne');

i = 0;
 
dow YAJL_ARRAY_LOOP(arrayOne:i:node1);
  arrayTwo = YAJL_object_find(node1:'arrayTwo');

  j = 0;

  dow YAJL_ARRAY_LOOP(arrayTwo:j:node2); 
    ..process array using node2
  enddo;

enddo;

 


Last edited 12/08/2023 at 12:27:07



freppa73@gmail.com

RE: RE: Parsing JSON using RPG with Scott Klement's Port of YAJL (Yet Another JSON Library) - Part 3

Posted:

RE: RE: Parsing JSON using RPG with Scott Klement's Port of YAJL (Yet Another JSON Library) - Part 3

Thanks I would look into it.


Last edited 12/08/2023 at 12:12:55




Reply




Copyright 1983-2024 BVSTools
GreenBoard(v3) Powered by the eRPG SDK, MAILTOOL Plus!, GreenTools for Google Apps, jQuery, jQuery UI, BlockUI, CKEditor and running on the IBM i (AKA AS/400, iSeries, System i).