reading JSON

Discussions relating to the ScottKlement.com port of the open source YAJL JSON Reader/Generator. This includes the YAJL tool as well as the YAJLR4, YAJLGEN, YAJLINTO and YAJLDTAGEN add-ons from ScottKlement.com. http://www.scottklement.com/yajl/
Post Reply
kundenancy@gmail.com
Posts: 7
Joined: Tue Aug 03, 2021 3:10 pm

reading JSON

Post by kundenancy@gmail.com »

I've done simple reads of JSON but this one is more complicated.

This is a snippet of the JSON response. I need to read the quotes. There are more quotes than displayed in the snippet.

Code: Select all

{
    "AllPickupLocationHaveCoverage": true,
    "Quote": "1149005634",
    "TotalNetCharge": {
        "Value": 86.3413,
        "Unit": "USD"
    },
    "OrderReferenceId": "POSOrderID12345",
    "Warnings": [
        "Error Code 9100: The freight class indicated doesn't match the one calculated for this shipment. Consider using the suggested freight class."
    ],
    "SuggestedFreightClasses": {
        "SKU12345": 50.0
    },
    "CompositeRateQuote": [
        {
            "Quotes": [
                {
                    "QuoteNumber": 1149005571,
                    "NetCharge": 943.622400,
                    "ServiceLevel": 351,
                    "Weight": 100.0,
                    "ServiceLevelDescription": "Back of Truck (No Liftgate)",
                    "ShipMethodCode": "Outside",
                    "CarrierName": "FragilePAK",
                    "CarrierLogo": "https://stgapi.freightclub.com/Content/Images/Logos/280.png",
                    "CarrierScacCode": "PBID",
                    "CarrierDescription": "short desc",
                    "ShipMethodName": "Back of Truck (No Liftgate)",
                    "ShipMethodShortDesc": "Basic Home Delivery",
                    "ShipMethodDescription": "short desc",
                    "TransitTime": "12 Business Day(s)",
                    "TransitDays": 12.0,
                    "PickUpTime": "Average pick-up timeframe is 3-5 business days from Ready Date",
                    "ProfileCarrierAccountId": null,
                    "TransitTimeInfo": "Time from booking to pick-up can vary, on average it is 2-Days. Estimated Transit times start from time of pick-up.",
                    "PickUpTimeInfo": "This is an estimate on how many days typically will be needed for the carrier to pick up from your origin point.",
                    "CarrierId": 280,
                    "BrokerId": 280,
                    "BrokerSCAC": "FCC",
                    "FinalMileCarrierScacCode": null,
                    "ClientContractServiceOptionType": null,
                    "InsuranceInfo": "Insurance removed by request.",
                    "CarrierWarning": null,
                    "TransitTimeSort": 12,
                    "ServiceGroup": null,
                    "ExtraServices": null,
                    "Warnings": [],
                    "MinPickupDate": "2022-04-08T00:00:00",
                    "MaxPickupDate": "2022-04-15T00:00:00",
                    "IsParcel": false
                },
                {
                    "QuoteNumber": 1149005515,
                    "NetCharge": 241.440528,
                    "ServiceLevel": 351,
                    "Weight": 100.0,
                    "ServiceLevelDescription": "Back of Truck (No Liftgate)",
                    "ShipMethodCode": "CURBSID",
                    "CarrierName": "Pilot Freight Services",
                    "CarrierLogo": "https://stgapi.freightclub.com/Content/Images/Logos/33.png",
                    "CarrierScacCode": "PILOT",
                    "CarrierDescription": "<p>Specializes in furniture and other commodities. Faster transit times due to their national coverage.</p>",
                    "ShipMethodName": "Back of Truck (No Liftgate)",
                    "ShipMethodShortDesc": "Delivery to the Dock",
                    "ShipMethodDescription": "short desc",
                    "TransitTime": "7 Business Day(s)",
                    "TransitDays": 7.0,
                    "PickUpTime": "Estimated average pick up timeframe is within 1-3 days of ready date.",
                    "ProfileCarrierAccountId": null,
                    "TransitTimeInfo": "Time from booking to pick-up can vary, on average it is 2-Days. Estimated Transit times start from time of pick-up.",
                    "PickUpTimeInfo": "This is an estimate on how many days typically will be needed for the carrier to pick up from your origin point.",
                    "CarrierId": 33,
                    "BrokerId": 33,
                    "BrokerSCAC": "FCC",
                    "FinalMileCarrierScacCode": null,
                    "ClientContractServiceOptionType": null,
                    "InsuranceInfo": "Insurance removed by request.",
                    "CarrierWarning": null,
                    "TransitTimeSort": 7,
                    "ServiceGroup": null,
                    "ExtraServices": null,
                    "Warnings": [],
                    "MinPickupDate": "2022-04-08T00:00:00",
                    "MaxPickupDate": "2022-04-13T00:00:00",
                    "IsParcel": false
},


This is snippet of my code

Code: Select all

         list = YAJL_object_find(docNode: 'CompositeRateQuote');


         i = 0;
         dow YAJL_ARRAY_LOOP( list: i: node );          

           val = YAJL_object_find(node: 'QuoteNumber');
           stringValue = yajl_get_string(val);
           Quot17 = %xlate(lw:up:(%xlate(NonDisplay:space:stringValue)));   

       enddo;
it isn't retrieving any of the fields I need

HELP
jonboy49
Posts: 200
Joined: Wed Jul 28, 2021 8:18 pm

Re: reading JSON

Post by jonboy49 »

At first glance this looks like a good use-case for DATA-INTO with YAJLINTO. Is there a specific reason for doing it the hard way?

If you use the YAJLGEN command it will even generate a best-guess DS for you to handle it. You'll need to adjust sizes and repeats but it will be simpler than the direct API approach.
Scott Klement
Site Admin
Posts: 635
Joined: Sun Jul 04, 2021 5:12 am

Re: reading JSON

Post by Scott Klement »

I added [code] and [/code] tags to your post because it was very difficult to read.

Then, I downloaded your JSON document. Since it wasn't a complete document, I manually added code to end the arrays and objects so that it would be a valid JSON document. Then saved it to my IFS.

Then I downloaded your RPG code. Again, there wasn't a complete program here, so I had to manually code enough of the RPG code so that I could try it out.

I noticed that you are trying to retrieve 'QuoteNumber' from within the 'CompositeRateQuote' objects... however, your JSON document has 'QuoteNumber' inside of 'Quotes'. I also noticed that QuoteNumber is numeric data and you're asking for a string. So I don't think the problem is that you're only getting the first QuoteNumber -- I can't see how you'd get anything at all the way this is coded.

Also, since 'Quotes' is an array, you'd need to loop through all of the array elements to get all of the QuoteNumber fields.

Here's the version of your JSON file that I'm testing with:

Code: Select all

{
    "AllPickupLocationHaveCoverage": true,
    "Quote": "1149005634",
    "TotalNetCharge": {
        "Value": 86.3413,
        "Unit": "USD"
    },
    "OrderReferenceId": "POSOrderID12345",
    "Warnings": [
        "Error Code 9100: The freight class indicated doesn't match the one calculated for this shipment. Consider using the suggested freight class."
    ],
    "SuggestedFreightClasses": {
        "SKU12345": 50.0
    },
    "CompositeRateQuote": [
        {
            "Quotes": [
                {
                    "QuoteNumber": 1149005571,
                    "NetCharge": 943.622400,
                    "ServiceLevel": 351,
                    "Weight": 100.0,
                    "ServiceLevelDescription": "Back of Truck (No Liftgate)",
                    "ShipMethodCode": "Outside",
                    "CarrierName": "FragilePAK",
                    "CarrierLogo": "https://stgapi.freightclub.com/Content/Images/Logos/280.png",
                    "CarrierScacCode": "PBID",
                    "CarrierDescription": "short desc",
                    "ShipMethodName": "Back of Truck (No Liftgate)",
                    "ShipMethodShortDesc": "Basic Home Delivery",
                    "ShipMethodDescription": "short desc",
                    "TransitTime": "12 Business Day(s)",
                    "TransitDays": 12.0,
                    "PickUpTime": "Average pick-up timeframe is 3-5 business days from Ready Date",
                    "ProfileCarrierAccountId": null,
                    "TransitTimeInfo": "Time from booking to pick-up can vary, on average it is 2-Days. Estimated Transit times start from time of pick-up.",
                    "PickUpTimeInfo": "This is an estimate on how many days typically will be needed for the carrier to pick up from your origin point.",
                    "CarrierId": 280,
                    "BrokerId": 280,
                    "BrokerSCAC": "FCC",
                    "FinalMileCarrierScacCode": null,
                    "ClientContractServiceOptionType": null,
                    "InsuranceInfo": "Insurance removed by request.",
                    "CarrierWarning": null,
                    "TransitTimeSort": 12,
                    "ServiceGroup": null,
                    "ExtraServices": null,
                    "Warnings": [],
                    "MinPickupDate": "2022-04-08T00:00:00",
                    "MaxPickupDate": "2022-04-15T00:00:00",
                    "IsParcel": false
                },
                {
                    "QuoteNumber": 1149005515,
                    "NetCharge": 241.440528,
                    "ServiceLevel": 351,
                    "Weight": 100.0,
                    "ServiceLevelDescription": "Back of Truck (No Liftgate)",
                    "ShipMethodCode": "CURBSID",
                    "CarrierName": "Pilot Freight Services",
                    "CarrierLogo": "https://stgapi.freightclub.com/Content/Images/Logos/33.png",
                    "CarrierScacCode": "PILOT",
                    "CarrierDescription": "<p>Specializes in furniture and other commodities. Faster transit times due to their national coverage.</p>",
                    "ShipMethodName": "Back of Truck (No Liftgate)",
                    "ShipMethodShortDesc": "Delivery to the Dock",
                    "ShipMethodDescription": "short desc",
                    "TransitTime": "7 Business Day(s)",
                    "TransitDays": 7.0,
                    "PickUpTime": "Estimated average pick up timeframe is within 1-3 days of ready date.",
                    "ProfileCarrierAccountId": null,
                    "TransitTimeInfo": "Time from booking to pick-up can vary, on average it is 2-Days. Estimated Transit times start from time of pick-up.",
                    "PickUpTimeInfo": "This is an estimate on how many days typically will be needed for the carrier to pick up from your origin point.",
                    "CarrierId": 33,
                    "BrokerId": 33,
                    "BrokerSCAC": "FCC",
                    "FinalMileCarrierScacCode": null,
                    "ClientContractServiceOptionType": null,
                    "InsuranceInfo": "Insurance removed by request.",
                    "CarrierWarning": null,
                    "TransitTimeSort": 7,
                    "ServiceGroup": null,
                    "ExtraServices": null,
                    "Warnings": [],
                    "MinPickupDate": "2022-04-08T00:00:00",
                    "MaxPickupDate": "2022-04-13T00:00:00",
                    "IsParcel": false
                }
            ]
        }
    ]
}
Here's my modified copy of your RPG code that retrieves the 'Quotes' variable, loops through it as an array, finds the 'QuoteNumber' field in each object in the array, and retrieves it as a number (rather than a string):

Code: Select all

**free
ctl-opt dftactgrp(*no) actgrp(*new) bnddir('YAJL') option(*srcstmt);

/copy yajl_h

dcl-s err         varchar(500);
dcl-s docNode     like(YAJL_VAL);
dcl-s cprList     like(YAJL_VAL);
dcl-s cprElem     like(YAJL_VAL);
dcl-s quotesList  like(YAJL_VAL);
dcl-s quotesElem  like(YAJL_VAL);
dcl-s quoteNumber like(YAJL_VAL);
dcl-s i           int(10);
dcl-s j           int(10);
dcl-s Quot17      packed(17: 0);
dcl-s testMsg     char(50);


docNode = yajl_stmf_load_tree('kundenancy/my.json': err);
if docNode = *null;
  // FIXME: display 'err' properly instead of a DSPLY hack
  testMsg = err;
  dsply testMsg;
  return;
endif;


cprList = YAJL_object_find(docNode: 'CompositeRateQuote');

i = 0;
dow YAJL_ARRAY_LOOP( cprList: i: cprElem );

  quotesList = YAJL_object_find(cprElem: 'Quotes');

  j = 0;
  dow YAJL_ARRAY_LOOP( quotesList: j: quotesElem);

    quoteNumber = YAJL_object_find(quotesElem: 'QuoteNumber');
    Quot17      = yajl_get_number(quoteNumber);
    testMsg = %char(Quot17);
    dsply testMsg;

  enddo;

enddo;

yajl_tree_free(docNode);

*inlr = *on; 
When I run this, it does DSPLY both of the quote numbers successfully.
kundenancy@gmail.com
Posts: 7
Joined: Tue Aug 03, 2021 3:10 pm

Re: reading JSON

Post by kundenancy@gmail.com »

Currently, our main IBMi is on V7R1. Another partition is on V7R2 where I had to run the program to get the response. Can DATA_INTO be used on those releases? FYI, there are plans to update them to V7R4 soon.

I didn't notice that Quote Number was numeric.

I had changed the array to Quotes but it didn't work. Maybe because I had quotenumber as char instead of numeric.

I will give this a try
Scott Klement
Site Admin
Posts: 635
Joined: Sun Jul 04, 2021 5:12 am

Re: reading JSON

Post by Scott Klement »

DATA-INTO requires 7.2
DATA-GEN requires 7.3
Scott Klement
Site Admin
Posts: 635
Joined: Sun Jul 04, 2021 5:12 am

Re: reading JSON

Post by Scott Klement »

It just occurred to me that your userid is (with spaces added) "Kunde Nancy @ gmail.com". It feels much friendlier now that I know your name :D

You said something about having trouble with "Quotes" as an array. That's one of the reasons I posted a complete sample program and JSON file, that way you can load it and run it on your system as is. This lets you step through it and learn from the code. (I know it works for the same reason, I loaded and ran it.)

Check it out, and let us know what you discover and how it works for you. That way, others can learn as well.

Good luck!
kundenancy@gmail.com
Posts: 7
Joined: Tue Aug 03, 2021 3:10 pm

Re: reading JSON

Post by kundenancy@gmail.com »

I knew I had to do 2 arrays but wasn't sure how to do. Your sample code was what I needed. I was able to process the JSON.

Thanks a lot for your help

Nancy
Post Reply