NULLs and empty structures
Unlike Genero BDL, JSON distinguishes NULL, empty and undefined elements.
JSON notation for NULL, empty and undefined
NULL
element is defined with the null
keyword. In the next example, the "name"
element is
null:{ "key":345, "name":null }
{ "key":345, "address":{} }
{ "key":345, "list":[] }
{ "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.
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.stringify(rec)
END MAIN
{"field1":999,"subarr":[]}
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
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
json_null="null"
attribute, the following
BDL elements will be represented with the null
keyword in the resulting JSON
string:- Simple primitive typed variables that are
NULL
, RECORD
variables where all members areNULL
,- Empty
DYNAMIC ARRAY
that contain zero elements.
IMPORT util
MAIN
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.format(util.JSON.stringify(rec))
END MAIN
{
"field1": null,
"field2": null,
"subrec1": null,
"subarr1": null
}
Using the json_null="undefined" attribute
json_null="undefined"
attribute, the
following BDL elements will be omitted in the resulting JSON string (with the exception of root
elements):- Simple primitive typed variables that are
NULL
(in fact,json_null="undefined"
is the default for primitive types), RECORD
variables where all members areNULL
,- Empty
DYNAMIC ARRAY
that contain zero elements. If some elements of a dynamic array areNULL
, the JSON serialization class must produce anull
keyword for these element, even when usingjson_null="undefined"
. This is mandatory because JSON requiresnull
keyword for undefined array elements. Otherwise, when omitted, the positions of array elements would be shifted.
IMPORT util
MAIN
DEFINE rec RECORD
field1 INTEGER ATTRIBUTES(json_null="undefined"),
field2 INTEGER, -- default is json_null="undefined" for primitives
subrec1 RECORD ATTRIBUTES(json_null="undefined")
field11 INTEGER,
fiedl12 VARCHAR(30)
END RECORD,
subrec2 RECORD -- will be serialized as {}
field21 INTEGER,
fiedl22 VARCHAR(30)
END RECORD,
subarr1 DYNAMIC ARRAY ATTRIBUTES(json_null="undefined") OF INTEGER,
subarr2 DYNAMIC ARRAY OF INTEGER, -- will be serialized as []
subarr3 DYNAMIC ARRAY ATTRIBUTES(json_null="undefined") OF INTEGER
END RECORD
INITIALIZE rec TO NULL
LET rec.field1 = 999
LET rec.subarr3[1] = NULL
LET rec.subarr3[2] = 888
DISPLAY util.JSON.format(util.JSON.stringify(rec))
END MAIN
{
"field1": 999,
"subrec2": {},
"subarr2": [],
"subarr3": [
null,
888
]
}
json_null="undefined"
attribute at the root
element, will be serialized as JSON null
, even if all members of the variable are
NULL
, because the root element cannot be omitted:IMPORT util
MAIN
VAR i INTEGER -- ATTRIBUTES(json_null="undefined") default for primitive types
LET i = NULL
DISPLAY "i: ", util.JSON.stringify(i)
VAR rec RECORD ATTRIBUTES(json_null="undefined")
field1 INTEGER
END RECORD
INITIALIZE rec.* TO NULL
DISPLAY "rec: ", util.JSON.stringify(rec)
VAR arr DYNAMIC ARRAY ATTRIBUTES(json_null="undefined") OF INTEGER
DISPLAY "arr: ", util.JSON.stringify(arr)
VAR sar ARRAY[10] ATTRIBUTES(json_null="undefined") OF INTEGER
INITIALIZE sar TO NULL
DISPLAY "sar: ", util.JSON.stringify(sar)
VAR dic DICTIONARY ATTRIBUTES(json_null="undefined") OF INTEGER
DISPLAY "dic: ", util.JSON.stringify(dic)
END MAIN
i: null
rec: null
arr: null
sar: null
dic: null