NULLs and empty structures

Unlike Genero BDL, JSON distinguishes NULL, empty and undefined elements.

JSON notation for NULL, empty and undefined

In JSON notation, a NULL element is defined with the null keyword. In the next example, the "name" element is null:
{ "key":345, "name":null }
Empty JSON objects are represented with an opening followed by a closing curly brace:
{ "key":345, "address":{} }
Empty JSON arrays are represented with an opening followed by a closing square brace:
{ "key":345, "list":[] }
Undefined elements do not appear in the JSON string representation. In the next example, the corresponding BDL record could have a "key" and "name" member. In the JSON notation, the "name" element is just omitted:
{ "key":345 }

States of Genero BDL variables

Genero BDL variables defined with a primitive type such as INTEGER can have a value or can be NULL, but they cannot be undefined as in JSON.

RECORD variables cannot be NULL. However, all elements of a RECORD can be NULL and thus the record can be considered as empty or null.

A DYNAMIC ARRAY containing zero elements can be considered as empty or null.

Controlling JSON serialization from BDL

By default, the util.JSON.stringify() method writes all elements of the BDL variable.

Sub-records and dynamic arrays are written to the JSON output:
DEFINE rec RECORD
           field1 INTEGER,
           subarr DYNAMIC ARRAY OF INTEGER
       END RECORD
INITIALIZE rec.* TO NULL
LET rec.field1 = 999
DISPLAY util.JSON.stringify(rec)
Produces following output:
{"field1":999,"subarr":[]}
If you want to omit all empty RECORD or DYNAMIC ARRAY elements in the JSON string, use the util.JSON.stringifyOmitNulls() method:
IMPORT util
MAIN
DEFINE rec RECORD
           field1 INTEGER,
           subarr DYNAMIC ARRAY OF INTEGER
       END RECORD
INITIALIZE rec.* TO NULL
LET rec.field1 = 999
DISPLAY util.JSON.stringifyOmitNulls(rec)
END MAIN
Produces following output (the subarr element is omitted because it is empty):
{"field1":999}

If you want to have a fine-grained control on the JSON serialization of null values and empty records and dynamic arrays, use the util.JSON.stringify() method, in conjunction with the json_null attribute when defining the BDL variable. The json_null variable definition attribute can be set to "null" or "undefined".

Using the json_null="null" attribute

When defining a BDL variable with the json_null="null" attribute, the following BDL elements will be represented with the null keyword in the resulting JSON string:
  1. Simple primitive variables that are NULL,
  2. RECORD variables where all members are NULL,
  3. Empty DYNAMIC ARRAY that contain zero elements.
In the next example, the sub-record and sub-array are written to the JSON output as nulls:
DEFINE rec RECORD
           field1 INTEGER ATTRIBUTES(json_null="null"),
           field2 CHAR(1) ATTRIBUTES(json_null="null"),
           subrec1 RECORD ATTRIBUTES(json_null="null")
               field11 INTEGER,
               fiedl12 VARCHAR(30)
           END RECORD,
           subarr1 DYNAMIC ARRAY ATTRIBUTES(json_null="null") OF INTEGER
       END RECORD
INITIALIZE rec.* TO NULL
DISPLAY util.JSON.stringify(rec)
Produces following output:
{"field1":null,"field2":null,"subrec1":null,"subarr1":null}

Using the json_null="undefined" attribute

When defining a BDL variable with the json_null="undefined" attribute, the following BDL elements will be omitted in the resulting JSON string:
  1. Simple primitive variables that are NULL (in fact, json_null="undefined" is the default for primitives),
  2. RECORD variables where all members are NULL,
  3. Empty DYNAMIC ARRAY that contain zero elements.
In the next example, all elements of the record (except field1) are omitted in the resulting JSON output:
DEFINE rec RECORD
           field1 INTEGER ATTRIBUTES(json_null="undefined"),
           field2 CHAR(1) ATTRIBUTES(json_null="undefined"),
           subrec1 RECORD ATTRIBUTES(json_null="undefined")
               field11 INTEGER,
               fiedl12 VARCHAR(30)
           END RECORD,
           subarr1 DYNAMIC ARRAY ATTRIBUTES(json_null="undefined") OF INTEGER
       END RECORD
INITIALIZE rec.* TO NULL
LET rec.field1 = 999
DISPLAY util.JSON.stringify(rec)
Produces following output:
{"field1":999}

Exception of NULL dynamic array elements

If elements of a dynamic array are NULL, the JSON serialization class will always produce a null keyword, even if you specify the json_null="undefined" attribute at the primitive type level.

This is mandatory because JSON requires null keyword for undefined array elements.
See the following example:
DEFINE rec RECORD
           subarr DYNAMIC ARRAY OF INTEGER ATTRIBUTES(json_null="undefined")
       END RECORD
INITIALIZE rec.* TO NULL
LET rec.subarr[3] = 999
DISPLAY util.JSON.stringify(rec) 
Produces this JSON output:
{"subarr":[null,null,999]}