• December 14, 2018

Parse JSON with U2 Dynamic Objects

UniVerse and UniData now have the ability to work with JSON or XML as an object, simplifying when you need to either create or consume those formats. As of UniVerse 11.1 and UniData 7.3, U2 Dynamic Objects (UDO for short) help you easily work with these formats.

Weather Service

To help us build our example, we’ll use a free online weather service that gets us some data that we can parse. Wunderground has a weather API for developers at http://www.wunderground.com/weather/api/, check out the details there, you can get a free account and API code that allows you to test the service.

What’s JSON?

JSON stands for JavaScript Object Notation and is a language-independent way of expressing data that is easy for data exchange using HTTP and it is commonly understood by many software languages. It is probably best to leave it to Wikipedia to explain it better if you are not familiar. Once you get your API key above, you can test the weather service and see exactly what is returned. Below is just a brief snippet to give you a quick glance at what it will look like. It’s important that you know the structure, because your code will need to know what to look for.

{
"response": {
    "version":"0.1",
},
"forecast":{
    "simpleforecast": 
        "forecastday": [
            {"date":{
                "epoch":"1421287200",
                "pretty":"7:00 PM MST on January 14, 2015",
....continued....

The Code

Let’s start by getting the JSON from the weather service:

** IMPORTANT ** You will have to get your own API key to call the service
apiKey = "0123abcd01234abcd"
city = "CO/Denver"
url = "http://api.wunderground.com/api/":apiKey:"/forecast/q/":city:".json"
method = "GET"
request = ""

st = createRequest(url, method, objRequest)
st = submitRequest(objRequest, 3600, "", headers, data, httpstatus)

At this point, if everything went right, then we should have JSON data in the data parameter.
IF UDORead(data, UDOFORMAT_JSON, RESTMSG) NE UDO_SUCCESS THEN GOSUB ERR
IF UDOGetProperty(RESTMSG, "forecast", forecast, UDOTYPE) NE UDO_SUCCESS THEN GOSUB ERR
IF UDOGetProperty(forecast, "simpleforecast", simple, UDOTYPE) NE UDO_SUCCESS THEN GOSUB ERR
IF UDOGetProperty(simple, "forecastday", arrDays, UDOTYPE) NE UDO_SUCCESS THEN GOSUB ERR

The UDORead function reads a JSON string from the first parameter and returns a UDO object in the third parameter if valid. Notice the parameters in the next 3 UDOGetProperty calls, we are traversing down the object tree, from forecast object to simpleforecast object to the forecastday array.Once we have the forecastday array, we can simply loop through each item and grab the values we are interested in. Just make sure you free the memory used by the UDO by calling UDOFree() when you are done.
LOOP
    GETSTAT = UDOArrayGetNextItem(arrDays, W.UDO, W.TYPE)
WHILE GETSTAT = UDO_SUCCESS DO
    i = i + 1
    IF UDOGetProperty(W.UDO, "date", UDO.DATE, UDOTYPE) NE UDO_SUCCESS THEN GOSUB ERR
    IF UDOGetProperty(UDO.DATE, "monthname", F.MONTH, UDOTYPE) NE UDO_SUCCESS THEN GOSUB ERR
    IF UDOGetProperty(UDO.DATE, "day", F.DAY, UDOTYPE) NE UDO_SUCCESS THEN GOSUB ERR
    IF UDOGetProperty(UDO.DATE, "year", F.YEAR, UDOTYPE) NE UDO_SUCCESS THEN GOSUB ERR
    IF UDOGetProperty(W.UDO, "high", UDO.HIGH, UDOTYPE) NE UDO_SUCCESS THEN GOSUB ERR
    IF UDOGetProperty(UDO.HIGH, "fahrenheit", HF, UDOTYPE) NE UDO_SUCCESS THEN GOSUB ERR
    IF UDOGetProperty(W.UDO, "low", UDO.LOW, UDOTYPE) NE UDO_SUCCESS THEN GOSUB ERR
    IF UDOGetProperty(UDO.LOW, "fahrenheit", LF, UDOTYPE) NE UDO_SUCCESS THEN GOSUB ERR
    IF UDOGetProperty(W.UDO, "conditions", CONDITIONS, UDOTYPE) NE UDO_SUCCESS THEN GOSUB ERR
    PRINT F.MONTH:" ":F.DAY:", ":F.YEAR
    PRINT "  High: ":HF:"    Low: ":LF
    PRINT "  Conditions: ":CONDITIONS
    PRINT
REPEAT

IF UDOFree(RESTMSG) NE UDO_SUCCESS THEN GOSUB ERR

The Result

Weather Forecast for CO/Denver

January 6, 2015
  High: 55    Low: 15
  Conditions: Partly Cloudy

January 7, 2015
  High: 34    Low: 27
  Conditions: Partly Cloudy

January 8, 2015
  High: 46    Low: 17
  Conditions: Partly Cloudy

January 9, 2015
  High: 32    Low: 18
  Conditions: Clear

Read The UDO Documentation

I’ve only touched on specific functions with this demo regarding UDO. To be thorough, you should probably read the documentation, found in the BASIC Extensions Manual. Click on the PDF next to UniVerse or UniData to get a list of all the available manuals.

Get The Code

If you want to try out this code, you can download it from GitHub
https://github.com/RocketSoftware/multivalue-lab/tree/master/U2/Demos/UDO/JSON/ConsumeWeather

Contact us to learn more about Rocket MultiValue Solutions.
Michael Byrne

Michael Byrne 6 Posts

Michael Byrne is a Principal Software Engineer in Customer Solutions for the Rocket U2 family of software. Michael specializes in helping customers understand modernization, REST, APIs, mobile, web, and more.

7 Comments

  • Nathan Reply

    March 22, 2016 at 12:33 pm

    Do I need to include anything for this to work? I currently get uninitialized variable warnings for UDO_SUCCESS and UDO_SUCCESS. I didn’t see anything in the documentation. I’m running Unidata 8.1.

  • Nathan Reply

    March 23, 2016 at 11:49 am

    Nevermind, needed to include UDO.H

    • Michael Byrne

      Michael Byrne Reply

      October 3, 2016 at 7:30 pm

      Glad you were able to get it working. You need to include UDO.H for any calls using UDO functions.

      • Ashwin Cyprian Reply

        February 1, 2017 at 6:10 am

        I am trying the same with the following data, but am getting an error code 3 (network error for submitRequest). but this is not happening when I try your code. could you please help?

        apiKey = “liMioR4WZSEIk2patM2NEGaj”
        address = “P.O. BOX 44198, 65 7TH STREET, DENMYR BUILDING”
        url = “https://api.trade.gov/consolidated_screening_list/search?api_key=”:apiKey:”&address=”:address:””

        method = “GET”
        request = “”

        st = createRequest(url, method, objRequest)
        st = submitRequest(objRequest, 3600, “”, headers, data, httpstatus)

        this url is working when i paste it in the browser.

        • Michael Byrne

          Michael Byrne Reply

          February 8, 2017 at 12:28 pm

          Hi Ashwin,

          There are two issues your code:
          1) Querystring parameters cannot have spaces or special characters in them, they must be URLENCODED. Replace all spaces with %20.
          2) This is a secure server, so you must create a secure request using createSecureRequest().

          This code should fix your problem:
          address = “P.O.%20BOX%2044198,%2065%207TH%20STREET,%20DENMYR%20BUILDING”
          url = “http://api.trade.gov/consolidated_screening_list/search?api_key=”:apiKey:”&address=”:address:””

          RCODE = createSecurityContext(ctx, “TLSv1”)
          IF RCODE THEN CRT “Unable to create SCR – Error Code (“:RCODE:”)”; STOP

          RCODE=createSecureRequest(url, METHOD, objRequest, ctx)
          IF RCODE THEN STOP “CreateSecureRequest error (“:RCODE:”)”

          * Uncomment protocolLogging if you need to log
          * ret1 = protocolLogging(“secureCallLog.LOG”,”ON”,”10″)
          RCODE=submitRequest(objRequest, 3600, “”, headers, data, httpstatus)
          * ret1 = protocolLogging(“secureCallLog.LOG”,”OFF”,”10″)
          IF RCODE THEN CRT; CRT “submitRequest error (“:RCODE:”) , HTTP Status: “:httpstatus; STOP

  • Damian Reply

    September 29, 2016 at 3:38 am

    Hi Is there a way to use xml in this instead of json cause I am just getting errors with the UDO_SUCCESS if i change the url to .xml instead of json and the UDOFORMAT_JSON to UDOFORMAT_XML?

    • Michael Byrne

      Michael Byrne Reply

      October 3, 2016 at 7:29 pm

      Thanks for reading, you can use XML, but you have to pay attention to what is returned from the Web service. If you look at the response from wunderground (simply use browser and type in URL), you’ll notice that they change the format and add an XML element named “forecastdays” to hold the “forecastday” elements. This is because there is no other way to represent an array like in JSON. So, if you add one more UDOGetProperty call for forecastdays, everything still works. I’ve included them below. (for brevity, I got rid of the ERR.HANDLER call)

      stat = UDOGetProperty(RESTMSG, “forecast”, forecast, UDOTYPE)
      stat = UDOGetProperty(forecast, “simpleforecast”, simple, UDOTYPE)
      stat = UDOGetProperty(simple, “forecastdays”, days, UDOTYPE)
      stat = UDOGetProperty(days, “forecastday”, arrDays, UDOTYPE)

Leave a Comment

Your email address will not be published. Required fields are marked *