Skip to main content
Hi all

Has 10.4 (or lower)  got the ability (function) to create (and read) JSON ? (I know that OpenInsight has) 

If not, is anyone prepared to share their version of such a function that they may have created?

I have written something to extract System Builder screens to convert them (into JSON) to HTML pages (using Python) but it may be interesting how others have approached this.

Thanks

------------------------------
Stefano Gallotta
Managing Member
Simply Red Open Systems
Milnerton ZA
------------------------------
Hi all

Has 10.4 (or lower)  got the ability (function) to create (and read) JSON ? (I know that OpenInsight has) 

If not, is anyone prepared to share their version of such a function that they may have created?

I have written something to extract System Builder screens to convert them (into JSON) to HTML pages (using Python) but it may be interesting how others have approached this.

Thanks

------------------------------
Stefano Gallotta
Managing Member
Simply Red Open Systems
Milnerton ZA
------------------------------
We do not have anything inside D3 ( 10.4 or earlier ) that natively creates JSON. We have the MVS Toolkit, our REST services tool, that will do that for you as middleware, and I've written a JSON field locater Pick BASIC subroutine:

SUBROUTINE GET.JSON.FIELD.SUB(D.NAME,ITXT,OTXT)
*
* Pass    D.NAME: The name of the JSON element (key)
*         ITXT:   JSON string
*
* Return  OTXT:   Dynamic array in which each attribute contains the
*                 contents of a JSON value (string, number or special
*                 value), array or object associated with that key.
*                 Special values include "true", "false" or "null".
*                 There will be one attribute for each orccurence
*                 of searched-for key specified in D.NAME.
*
* This routine can be recalled on its own result string to extract
* nested data. For example, you can have a key "Customers" whose
* value is an object containing an array that contains three objects,
* each of which has the key "Customer" and contains "CustName",
* "CustPhone" and "CustEmail". To extract each customer's information
* one customer at a time, you would call the routine multiple times
* as follows:
*
*  CALL GET.JSON.FIELD.SUB("Customer",JSONSTR,SUBSTR)
*  ATTR.CNT = DCOUNT(SUBSTR,@AM)
*  FOR AX = 1 TO ATTR.CNT
*    CALL GET.JSON.FIELD.SUB("CustName",SUBSTR<AX>,CNAME)
*    CALL GET.JSON.FIELD.SUB("CustPhone",SUBSTR<AX>,PHONE)
*    GOSUB UpdatePhoneList
*  NEXT AX
*
*  You can also bypass the extraction of the container objects
*  by searching for a key that occurs within the container object
*  one or more times and return the value only, like so:
*
*  CALL GET.JSON.FIELD.SUB("CustEmail",JSONSTR,EMAILS)
*  ATTR.CNT = DCOUNT(EMAILS,@AM)
*  FOR AX = 1 TO ATTR.CNT
*    EMAIL = EMAILS<AX>
*    GOSUB ProcessEmail
*  NEXT AX
*
*
   WTXT=ITXT  ;* ITXT should remain untouched.
              ;* Move it to WTXT and remove trivial characters
   CONVERT @AM:@VM:@SVM:CHAR(9):CHAR(10):CHAR(13) TO "" IN WTXT
   OTXT=""            ;* Set up return dynamic array, its subscript,
   OTXT.X=0           ;* the input string length and the search
   WTXT.LEN=LEN(WTXT) ;* argument in double quotes
   SEARCH.NAME=\\"\\:D.NAME:\\"\\
   SEARCH.LEN=LEN(SEARCH.NAME)
*
   FOR IPOS=1 TO WTXT.LEN
     IF WTXT[IPOS,SEARCH.LEN]=SEARCH.NAME THEN ;* found name
       IPOS+=SEARCH.LEN
       FOUND.DELIM=INDEX(WTXT[IPOS,WTXT.LEN],\\:\\,1)
       IF FOUND.DELIM ELSE GO SubroutineMainExit
       IPOS+=FOUND.DELIM
       FOUND.CHAR=""
       FOUND.BEG=""
       FOUND.LEN=""
       SEARCH.CHAR=""
       WQUOTE=INDEX(WTXT[IPOS,WTXT.LEN],\\"\\,1)
       WBRACE=INDEX(WTXT[IPOS,WTXT.LEN],\\{\\,1)
       WBRACK=INDEX(WTXT[IPOS,WTXT.LEN],\\[\\,1)
       WCOMMA=INDEX(WTXT[IPOS,WTXT.LEN],\\,\\,1)
       IF WQUOTE ELSE WQUOTE=WTXT.LEN
       IF WBRACE ELSE WBRACE=WTXT.LEN
       IF WBRACK ELSE WBRACK=WTXT.LEN
       IF WCOMMA ELSE WCOMMA=WTXT.LEN
       IF WCOMMA<WQUOTE AND WCOMMA<WBRACE AND WCOMMA<WBRACK THEN
         OTXT.X+=1
         OTXT<OTXT.X>=TRIM(WTXT[IPOS,WCOMMA-1])
       END ELSE
         LOOP WHILE FOUND.CHAR="" DO
           WCH=WTXT[IPOS,1]
           BEGIN CASE
             CASE IPOS>WTXT.LEN
               EXIT
             CASE WCH="{"
               FOUND.CHAR=WCH
               FOUND.BEG=IPOS
               SEARCH.CHAR="}"
             CASE WCH=\\"\\
               FOUND.CHAR=WCH
               FOUND.BEG=IPOS
               SEARCH.CHAR=WCH
             CASE WCH="["
               FOUND.CHAR=WCH
               FOUND.BEG=IPOS
               SEARCH.CHAR="]"
           END CASE
           IPOS+=1
         REPEAT
         IF FOUND.CHAR="" THEN GO SubroutineMainExit
         FOUND.COUNT=1
         LOOP WHILE FOUND.COUNT>0 DO
           WCH=WTXT[IPOS,1]
           BEGIN CASE
             CASE IPOS>WTXT.LEN
               EXIT
             CASE WCH=SEARCH.CHAR
               FOUND.COUNT-=1
               IF FOUND.COUNT<1 THEN
                 FOUND.LEN=(IPOS-FOUND.BEG)+1
                 IF SEARCH.CHAR=\\"\\ THEN
                   FOUND.BEG+=1
                   FOUND.LEN-=2
                 END
                 OTXT.X+=1
                 OTXT<OTXT.X>=WTXT[FOUND.BEG,FOUND.LEN]
               END
             CASE WCH=FOUND.CHAR
               FOUND.COUNT+=1
           END CASE
           IPOS+=1
         REPEAT
       END
     END
   NEXT IPOS
*
SubroutineMainExit:
   RETURN
*
* End of source


------------------------------
Brian S. Cram
Principal Technical Support Engineer
Rocket Software
------------------------------
We do not have anything inside D3 ( 10.4 or earlier ) that natively creates JSON. We have the MVS Toolkit, our REST services tool, that will do that for you as middleware, and I've written a JSON field locater Pick BASIC subroutine:

SUBROUTINE GET.JSON.FIELD.SUB(D.NAME,ITXT,OTXT)
*
* Pass    D.NAME: The name of the JSON element (key)
*         ITXT:   JSON string
*
* Return  OTXT:   Dynamic array in which each attribute contains the
*                 contents of a JSON value (string, number or special
*                 value), array or object associated with that key.
*                 Special values include "true", "false" or "null".
*                 There will be one attribute for each orccurence
*                 of searched-for key specified in D.NAME.
*
* This routine can be recalled on its own result string to extract
* nested data. For example, you can have a key "Customers" whose
* value is an object containing an array that contains three objects,
* each of which has the key "Customer" and contains "CustName",
* "CustPhone" and "CustEmail". To extract each customer's information
* one customer at a time, you would call the routine multiple times
* as follows:
*
*  CALL GET.JSON.FIELD.SUB("Customer",JSONSTR,SUBSTR)
*  ATTR.CNT = DCOUNT(SUBSTR,@AM)
*  FOR AX = 1 TO ATTR.CNT
*    CALL GET.JSON.FIELD.SUB("CustName",SUBSTR<AX>,CNAME)
*    CALL GET.JSON.FIELD.SUB("CustPhone",SUBSTR<AX>,PHONE)
*    GOSUB UpdatePhoneList
*  NEXT AX
*
*  You can also bypass the extraction of the container objects
*  by searching for a key that occurs within the container object
*  one or more times and return the value only, like so:
*
*  CALL GET.JSON.FIELD.SUB("CustEmail",JSONSTR,EMAILS)
*  ATTR.CNT = DCOUNT(EMAILS,@AM)
*  FOR AX = 1 TO ATTR.CNT
*    EMAIL = EMAILS<AX>
*    GOSUB ProcessEmail
*  NEXT AX
*
*
   WTXT=ITXT  ;* ITXT should remain untouched.
              ;* Move it to WTXT and remove trivial characters
   CONVERT @AM:@VM:@SVM:CHAR(9):CHAR(10):CHAR(13) TO "" IN WTXT
   OTXT=""            ;* Set up return dynamic array, its subscript,
   OTXT.X=0           ;* the input string length and the search
   WTXT.LEN=LEN(WTXT) ;* argument in double quotes
   SEARCH.NAME=\\"\\:D.NAME:\\"\\
   SEARCH.LEN=LEN(SEARCH.NAME)
*
   FOR IPOS=1 TO WTXT.LEN
     IF WTXT[IPOS,SEARCH.LEN]=SEARCH.NAME THEN ;* found name
       IPOS+=SEARCH.LEN
       FOUND.DELIM=INDEX(WTXT[IPOS,WTXT.LEN],\\:\\,1)
       IF FOUND.DELIM ELSE GO SubroutineMainExit
       IPOS+=FOUND.DELIM
       FOUND.CHAR=""
       FOUND.BEG=""
       FOUND.LEN=""
       SEARCH.CHAR=""
       WQUOTE=INDEX(WTXT[IPOS,WTXT.LEN],\\"\\,1)
       WBRACE=INDEX(WTXT[IPOS,WTXT.LEN],\\{\\,1)
       WBRACK=INDEX(WTXT[IPOS,WTXT.LEN],\\[\\,1)
       WCOMMA=INDEX(WTXT[IPOS,WTXT.LEN],\\,\\,1)
       IF WQUOTE ELSE WQUOTE=WTXT.LEN
       IF WBRACE ELSE WBRACE=WTXT.LEN
       IF WBRACK ELSE WBRACK=WTXT.LEN
       IF WCOMMA ELSE WCOMMA=WTXT.LEN
       IF WCOMMA<WQUOTE AND WCOMMA<WBRACE AND WCOMMA<WBRACK THEN
         OTXT.X+=1
         OTXT<OTXT.X>=TRIM(WTXT[IPOS,WCOMMA-1])
       END ELSE
         LOOP WHILE FOUND.CHAR="" DO
           WCH=WTXT[IPOS,1]
           BEGIN CASE
             CASE IPOS>WTXT.LEN
               EXIT
             CASE WCH="{"
               FOUND.CHAR=WCH
               FOUND.BEG=IPOS
               SEARCH.CHAR="}"
             CASE WCH=\\"\\
               FOUND.CHAR=WCH
               FOUND.BEG=IPOS
               SEARCH.CHAR=WCH
             CASE WCH="["
               FOUND.CHAR=WCH
               FOUND.BEG=IPOS
               SEARCH.CHAR="]"
           END CASE
           IPOS+=1
         REPEAT
         IF FOUND.CHAR="" THEN GO SubroutineMainExit
         FOUND.COUNT=1
         LOOP WHILE FOUND.COUNT>0 DO
           WCH=WTXT[IPOS,1]
           BEGIN CASE
             CASE IPOS>WTXT.LEN
               EXIT
             CASE WCH=SEARCH.CHAR
               FOUND.COUNT-=1
               IF FOUND.COUNT<1 THEN
                 FOUND.LEN=(IPOS-FOUND.BEG)+1
                 IF SEARCH.CHAR=\\"\\ THEN
                   FOUND.BEG+=1
                   FOUND.LEN-=2
                 END
                 OTXT.X+=1
                 OTXT<OTXT.X>=WTXT[FOUND.BEG,FOUND.LEN]
               END
             CASE WCH=FOUND.CHAR
               FOUND.COUNT+=1
           END CASE
           IPOS+=1
         REPEAT
       END
     END
   NEXT IPOS
*
SubroutineMainExit:
   RETURN
*
* End of source


------------------------------
Brian S. Cram
Principal Technical Support Engineer
Rocket Software
------------------------------
Excellent - Thanks Brian, I;ll have a look at this.

------------------------------
Stefano Gallotta
Managing Member
Simply Red Open Systems
Milnerton ZA
------------------------------
Hi all

Has 10.4 (or lower)  got the ability (function) to create (and read) JSON ? (I know that OpenInsight has) 

If not, is anyone prepared to share their version of such a function that they may have created?

I have written something to extract System Builder screens to convert them (into JSON) to HTML pages (using Python) but it may be interesting how others have approached this.

Thanks

------------------------------
Stefano Gallotta
Managing Member
Simply Red Open Systems
Milnerton ZA
------------------------------
Methinks life would be so much easier with an SB+ upgrade.

------------------------------
Alex Polglaze

The Book-Keeping Network
Perth Western Australia
+61419 776 348
apolglaze@book-keepingnetwork.com.au
https://www.book-keepingnetwork.com.au/
------------------------------
Methinks life would be so much easier with an SB+ upgrade.

------------------------------
Alex Polglaze

The Book-Keeping Network
Perth Western Australia
+61419 776 348
apolglaze@book-keepingnetwork.com.au
https://www.book-keepingnetwork.com.au/
------------------------------
@Alex Polglaze Just to put things into context; the exercise was one merely to see how far I could push my HTML / CSS skills from a character-based screen.

There was no notion of "an upgrade" as such. But, yes SB+ may be considered.

Thanks :)

Stefano​​​

------------------------------
Stefano Gallotta
Managing Member
Simply Red Open Systems
Milnerton ZA
------------------------------
@Alex Polglaze Just to put things into context; the exercise was one merely to see how far I could push my HTML / CSS skills from a character-based screen.

There was no notion of "an upgrade" as such. But, yes SB+ may be considered.

Thanks :)

Stefano​​​

------------------------------
Stefano Gallotta
Managing Member
Simply Red Open Systems
Milnerton ZA
------------------------------
It wasn't meant for you personally, but rather a subtle hint to Rocket, that there are a lot of us who would really like an SB+ upgrade with all of the new functionality that is apparently available, being included or more easily accessible. HINT, HINT.

------------------------------
Alex Polglaze

The Book-Keeping Network
Perth Western Australia
+61419 776 348
apolglaze@book-keepingnetwork.com.au
https://www.book-keepingnetwork.com.au/
------------------------------
Hi all

Has 10.4 (or lower)  got the ability (function) to create (and read) JSON ? (I know that OpenInsight has) 

If not, is anyone prepared to share their version of such a function that they may have created?

I have written something to extract System Builder screens to convert them (into JSON) to HTML pages (using Python) but it may be interesting how others have approached this.

Thanks

------------------------------
Stefano Gallotta
Managing Member
Simply Red Open Systems
Milnerton ZA
------------------------------
hi; If its the embedded nature of JSON that you want a solution to. I have the algorithmns that will process it.
I associate a branch count with the node values and (in a pickish fashion) stack the counts and count my way through them.

------------------------------
Robert Davenport
Programmer
Custom Language Solutions
Auckland NZ
------------------------------
Hi all

Has 10.4 (or lower)  got the ability (function) to create (and read) JSON ? (I know that OpenInsight has) 

If not, is anyone prepared to share their version of such a function that they may have created?

I have written something to extract System Builder screens to convert them (into JSON) to HTML pages (using Python) but it may be interesting how others have approached this.

Thanks

------------------------------
Stefano Gallotta
Managing Member
Simply Red Open Systems
Milnerton ZA
------------------------------
When first starting to work with json, we were receiving json communication from one of our vendors.  So, the first thing I wanted to do was to be able to read it.  I spent quite some time working on breaking it down in d3 and finally succeeded.   Then sometime later, I found this Python function (json.dumps) that works great.  Here is sample code which extracts the json and makes it readable.  Check it out.

! This program demonstrates how raw json can be displayed
! in a readable format using the python json.dumps() module.
! I am only using the "indent" option with json.dumps().
!
! Over all steps
! 1. Read the json to be converted
! 2. Setup or read the python script
! 3. Swap in the json to the script
! 4. Open a Linux directory
! 5. Write the python script to the directory
! 6. Make the script executable
! 7. Execute the python script with output to the screen (may be captured)
! 8. Or write the reply to a file for visual review by editing it
!
! Take the json and set it to a variable (read from a file)
! This should be only in the first attribute.
   raw.json = \\{"name":"John","age":30,"married":True,"divorced":False,"children":("Ann","Billy"),"pets":None,"cars":[{"model":"BMW 230","mpg":27.5},{"model":"Ford Edge","mpg":24.1}]}\\
!
! Body
!
! Python script (may be read from a file)
   python = "#!/usr/bin/python2"
   python<2> = \\import json\\
   python<3> = \\answer = (json.dumps(raw.json, indent=4))\\
   python<4> = \\print (answer)\\
   python = swap(python,"raw.json",raw.json)
!
! Open the directory (this can be any directory that you have access to)
   open "/tmp" to tmp.dir else crt "cannot open /tmp"; stop
!
! Write the script to the home directory
   write python on tmp.dir,"ext.json.py"
!
! Make the script executable
   execute "!chmod 755 /tmp/ext.json.py"
!
! Execute the script with output to the screen
   execute "!/tmp/ext.json.py"
!
! Or, you may edit output for review
! Write the output to a file for viewing
   execute "!/tmp/ext.json.py" capturing reply
   write reply on tmp.dir,"reply.json"
!
! Edit the output
   data "p"
   execute "ed /tmp reply.json"
end

------------------------------
Ted Hurlbut
DBA
AMECO - American Equipment Co
Greenville SC US
------------------------------