OpenAPI types mapping: BDL

Conversion mapping for Genero BDL data types in OpenAPI documentation.

Table 1. OpenAPI (JSON) data types mapping for Genero BDL data types
Genero BDL data types JSON data types Format Additional format keywords
STRING STRING
VARCHAR(5) STRING maxLength: 5

For an example, go to VARCHAR(N)

CHAR STRING
DATE STRING format: date For examples of date conversion, go to DATE/DATETIME
DATETIME YEAR TO SECOND STRING format: date-time For examples of datetime conversion, go to DATE/DATETIME
INTERVAL DAY(5) TO SECOND STRING
TEXT STRING
BYTE STRING format: binary
BOOLEAN BOOLEAN
INTEGER INTEGER

format: int32

TINYINT INTEGER
SMALLINT INTEGER
BIGINT INTEGER

format: int64  

DECIMAL NUMBER For examples of decimal conversion, go to DECIMAL(p,s)
SMALLFLOAT NUMBER format: float
FLOAT NUMBER format: double
MONEY NUMBER format: double

multipleOf: 0.01

minimum:-100000000000000

exclusiveMinimum: true

maximum: 100000000000000

exclusiveMaximum: true

RECORD OBJECT
DYNAMIC ARRAY OF ARRAY For examples handling nulls in arrays, go to Example 2: Handling arrays with null values
ARRAY [ ] OF N/A N/A
DICTIONARY OF OBJECT additionalProperties:"type":"object"
util.JSONObject OBJECT additionalProperties: {}
util.JSONArray OBJECT additionalProperties: {}
json_null="null" attribute set to allow null values to deserialize JSON null values ​​into BDL variables, or to enable serialization of null values from BDL to JSON. All primitive and complex data types nullable: true For examples, go to Example 1: Primitive and complex types with null values

Data type conversion

In high-level RESTful Web services the GWS can refine data types using JSON schema restriction keywords in the schema for types.

The OpenAPI specification defines data types for basic types, such as string, date, and number. These generally correspond to Genero BDL primitive data types.

When you need to restrict a data type (for example, to match data constraints defined on a database), the GWS can refine data types by applying JSON attribute keywords to the type specification in the schema it generates. The following sections describe how the GWS refines data types for VARCHAR, DATE/DATETIME, DECIMAL(P,S), and primitive and complex types with null values.

VARCHAR(N)

OpenAPI defines variable-length character string data as a string. For a string type to define a VARCHAR(N) of length N, the GWS can restrict its size by using the maxLength keyword.
schema	
type           "string"
maxLength	10

fglrestful generates the data type in the client stub, mapping it to a Genero BDL VARCHAR(10) type.

DATE/DATETIME

OpenAPI defines a date type as a string. The format keyword can give this as a full date (2021-07-15), or as a date-time (2021-07-15T16:39:28Z).

As a DATE

schema	
type         "string"
format       "date"

fglrestful generates the data type in the client stub, mapping it to a Genero BDL DATE type.

As a DATETIME

schema	
type         "string"
format       "date-time"

fglrestful generates the data type in the client stub, mapping it to a Genero BDL DATETIME YEAR TO SECOND type.

By default fglrestful generates DATETIME YEAR TO SECOND. You can configure how the GWS refines the fraction part of a DATETIME type at the command level. For example, to generate DATETIME YEAR TO FRACTION(3), you can set the option --datetime-fraction=3 in the fglrestful tool command.

DECIMAL(p,s)

OpenAPI defines a fixed point decimal type as a number. For a number type to represent a fixed point decimal with precision and scale (a Genero BDL DECIMAL(p,s)), the GWS defines it with several JSON schema restriction keywords:
schema	
type	           "number"
multipleOf	      0.01
minimum	        -1000
exclusiveMinimum	true
maximum	         1000
exclusiveMaximum	true
With this example, fglrestful does the conversion for the number type schema definition as follows:
  • The precision (p) is calculated from the maximum and minimum values. The maximum is calculated by subtracting the multipleOf value from the maximum:
    Maximum = 1000 - 0.01 = 999.99
    The minimum is calculate by adding the multipleOf to the minimum:
    Minimum = -1000 + 0.01 = -999.99
    If the keywords exclusiveMinimum and exclusiveMaximum are set to true, the corresponding boundary is excluded. In the example, the minimum value (-1000) and the maximum (1000) are excluded.
  • To calculate the scale (s), fglrestful does a conversion based on the value of the multipleOf attribute. multipleOf can have two values:
    • multipleOf = 0.01 is converted to DECIMAL(p,2), meaning the number of size p has two decimal places.
    • multipleOf = 1 is converted to DECIMAL(p,0), meaning the number of size p has no decimal place.
    • If there is no multipleOf, the number is converted to DECIMAL(p), meaning it can be any number of size p with or without decimals. There is no fixed decimal place.

In this example, fglrestful generates the data type in the client stub, mapping it to a Genero BDL DECIMAL(5,2) type. The fraction is written as DECIMAL(5,2) because five digits are needed for the precision and the scale, for example 999.99.

Examples

Data type conversion examples with null values.

Example 1: Primitive and complex types with null values

According to the standard set by OpenAPI 3.0, null values in all primitive and complex data types are represented with the nullable: true property.

BDL variables must either:
  • have the json_null="null" attribute set to accept NULL values ​ ​in addition to its standard type (for example, STRING)
  • or the option to allow nulls globally with the allowNullAsDefault option must be set for the The json.Serializer class.
Serialization error-15807 is thrown if null values are not handled in your code by either of the above methods.
There is a special case when you define records as types in your Genero BDL code with json_null="null". For example, the tAddress record type may have null values:
TYPE tAddress RECORD
    street STRING,
    city STRING,
    state STRING,
    zip STRING
END RECORD

TYPE customer RECORD
    lastname STRING ATTRIBUTES(json_null="null"),
    firstname STRING,
    address tAddress ATTRIBUTE(json_null="null")
END RECORD
In this example, fglrestful handles the mapping of the Genero BDL type to the JSON object schema as follows:
  • the nullable: true property is set.
  • the anyOf property is set to allow fields to accept either the expected type or NULL
  • the tAddress type is defined in a reference ($ref) to the components/schemas section where its schema will be defined.
It is a constraint of OpenAPI to wrap a reference ($ref) in an anyOf property to allow it to be a sibling with the nullable property, as shown in this example from the OpenAPI document.
 "content": {
	"application/json": {
	    "schema": {
		  "type": "object",
		   "properties": {
			 "lastname": {
			     "type": "string",
			     "nullable": true
			 },
			 "firstname": {
			     "type": "string"
			 },
			 "address": {
			     "nullable": true,
			     "anyOf": [
			        {
			         "$ref": "#/components/schemas/tAddress"
			        }
			     ]
		         },
To learn more about the OpenAPI specification, refer to the OpenAPI documentation.

Example 2: Handling arrays with null values

This program reads data, including null values, into the array arr. It converts the array to a JSON string and attempts to write a formatted JSON string to the standard output. Calls to the conversion methods are enclosed in a TRY/CATCH block to detect potential JSON format errors.

 # ... 
 DEFINE t TEXT
 DEFINE writer json.JSONWriter
 DEFINE arr DYNAMIC ARRAY OF STRING
    LOCATE t IN MEMORY
    INITIALIZE t to NULL

    LET arr[1] = "foo"
    LET arr[2] = NULL
    LET arr[3] = NULL

    TRY 
        LET writer = json.JSONWriter.Create()
        CALL writer.setOutputCharset("UTF-8")
        CALL writer.writeToText(t)
        CALL writer.startJSON()
        CALL json.Serializer.variableToJSON(arr, writer)
        CALL writer.endJSON()
        CALL writer.close()
    CATCH
        DISPLAY "\narr with NULL value:" || "ERROR " || status || " " || sqlca.sqlerrm
    END TRY
    # ...

The call to serialize this array will raise error-15807:

arr with NULL value:ERROR -15807 Array cannot serialize 'null' elements. It requires json_null="null"
A NULL element can only be serialized if it is explicitly indicated with json_null="null" on the element type:
DEFINE arr DYNAMIC ARRAY OF STRING ATTRIBUTE(json_null="null")
Or if the allowNullAsDefault option of the The json.Serializer class is set to 1 to allow null values globally:
CALL json.Serializer.setOption( "allowNullAsDefault", 1 )
For more details, go to Serializer options.
If the entire array is NULL, for example:
INITIALIZE arr TO NULL
the error is not raised and the GWS will serialize it to {} or to null if you put the json_null="null" attribute on the array:
DEFINE arr DYNAMIC ARRAY ATTRIBUTE(json_null="null") OF STRING ATTRIBUTE(json_null="null")