Ask Reuben

Array Attributes of Record Attributes

Why is the ATTRIBUTES being ignored for my ARRAY OF RECORD?

Why is the ATTRIBUTES being ignored for my ARRAY OF DICTIONARY?

I have seen this mistake a few times now so I felt it deserves an article.  It occurs when you attempt to use the ATTRIBUTES clause on a DYNAMIC ARRAY OF RECORD.  It looks like the ATTRIBUTES clause is being ignored but what has actually happened is that you have put it in the wrong place, you have added it to the RECORD when you should add it to the ARRAY. (Note: where I say ARRAY you can also substitute DICTIONARY)

Take a code example such as the following …


IMPORT util
DEFINE data RECORD
    hdr RECORD 
        idx INTEGER,
        desc STRING 
    END RECORD,
    dtl DYNAMIC ARRAY OF RECORD 
        idx INTEGER ,
        desc  STRING
    END RECORD
END RECORD

MAIN
    LET data.hdr.idx = 1
    LET data.hdr.desc = "AAA"
    
    LET data.dtl[1].idx = 1
    LET data.dtl[1].desc= "A"
    LET data.dtl[2].idx = 2
    LET data.dtl[2].desc= "B"
    
    DISPLAY util.JSON.stringify(data) 
END MAIN

… this may generate the following output …

{"hdr":{"idx":1,"desc":"AAA"},"dtl":[{"idx":1,"desc":"A"},{"idx":2,"desc":"B"}]}

… you decide that “hdr”, “dtl”, you want to appear as the more meaningful “header” and “detail”.  So in the record definition, you use the ATTRIBUTES clause to specify the name of the identifier that will appear if this is output as JSON.

So your record definition is now …


DEFINE data RECORD
    hdr RECORD ATTRIBUTES(json_name="header")
        idx INTEGER,
        desc STRING
    END RECORD,
    dtl DYNAMIC ARRAY OF RECORD  ATTRIBUTES(json_name="detail")
        idx INTEGER,
        desc  STRING 
    END RECORD
END RECORD

… that is you have used the ATTRIBUTES to specify a json_name for the two parts.  However the output when you run the program is …

{"header":{"idx":1,"desc":"AAA"},"dtl":[{"idx":1,"desc":"A"},{"idx":2,"desc":"B"}]}

… hdr has become header, but dtl is still dtl and not the expected detail.

There is a fairly simple explanation.  the ATTRIBUTES for the second part has been put in the wrong place in the code.  The record definition should be …


DEFINE data RECORD
    hdr RECORD ATTRIBUTES(json_name="header")
        idx INTEGER,
        desc STRING
    END RECORD,
    dtl DYNAMIC ARRAY ATTRIBUTES(json_name="detail") OF RECORD 
        idx INTEGER,
        desc  STRING
    END RECORD
END RECORD

… and now you get the expected output of …

{"header":{"idx":1,"desc":"AAA"},"detail":[{"idx":1,"desc":"A"},{"idx":2,"desc":"B"}]}

… that is hdr has become header and dtl has become detail.

So where you have a DYNAMIC ARRAY OF RECORD, you can …

  • define the ATTRIBUTES for the ARRAY only – DYNAMIC ARRAY ATTRIBUTES(...) OF RECORD 
  • define the ATTRIBUTES for the RECORD only – DYNAMIC ARRAY OF RECORD ATTRIBUTES(...)
  • define ATTRIBUTES for both ARRAY and RECORD – DYNAMIC ARRAY ATTRIBUTES(...) OF RECORD  ATTRIBUTES(...)

… the trick is remembering that there are two places the ATTRIBUTES clause can be used in that one line of code and to pick the right place(s).