JSON schema to PL/I mapping

The DFHJS2LS utility program supports mappings between JSON schemas and PL/I data structures. Because the Enterprise PL/I compiler and older PL/I compilers differ, two language options are supported: PLI-ENTERPRISE and PLI-OTHER.

Rules for mapping schema element names to PL/I

The CICS® assistants generate unique and valid names for PL/I variables from the schema element names using the following rules:
  1. Characters other than A-Z, a-z, 0-9, @, #, _, or $ are replaced with ' X '.

    For example, monthly-total becomes monthlyXtotal.

    You can use the MAPPING-OVERRIDES parameter to change the way other characters are handled. For example, if you set the value HYPHENS-AS-UNDERSCORES , any hyphen in the JSON schema is converted to an underscore instead of an X. For example, monthly-total becomes monthly_total.

  2. Duplicate names in the same scope are made unique by the addition of one or two numeric digits to the second and subsequent instances of the name.

    For example, three instances of year become year , year1 , and year2.

    Should the above behavior be undesirable the user can specify MAPPING-OVERRIDES=NO-ARRAY-NAME-INDEXING as input to the utility which disables the addition of one or two numeric digits to the second and subsequent instances of the name.

  3. A JSON schema specifies that a variable has varying cardinality if it has a "type" value of "array" , and the keywords "minItems" and "maxItems" are omitted or have different values. If the schema specifies that the variable has varying cardinality, then field names are created with suffixes of "_cont" and "_num".

    For more information, see Variable arrays of elements in DFHJS2LS.

  4. A JSON schema specifies that a variable is optional if it does not appear in the "required" keyword array that is associated with the enclosing JSON schema "object" type. For optional fields, an additional field is generated with a suffix of _num added to the element name. At run time this is zero to indicate the value was absent from the JSON data, and non-zero if the value was present in the JSON data.
  5. Field names are limited to 31 characters. If a generated name, including any prefix and suffix, exceeds this length, the element name is truncated.
The total length of the resulting name is 31 characters or less.

Rules for mapping schema types to PL/I

DFHJS2LS maps schema type values to PL/I data types according to the following table. Also note the following points:
  • If the MAPPING-LEVEL parameter is set to 1.2 or higher and the CHAR-VARYING parameter is set to NULL, variable-length character data is mapped to null-terminated strings and an extra character is allocated for the null-terminator.
  • If the MAPPING-LEVEL parameter is set to 1.2 or higher and the CHAR-VARYING parameter is not specified, by default variable-length character data is mapped to a VARYINGZ data type for Enterprise PL/I and VARYING data type for Other PL/I.
  • Variable-length binary data is mapped to a VARYING data type if it less than 32 768 bytes and to a container if it is more than 32 768 bytes.
JSON Schema keyword PL/I data description
All of:
"type":"null"
"type": []
"allOf"
"anyOf"
"noneOf"
"not"

Not supported

"$schema":"http://json-schema.org/draft-04/schema#"

This keyword is ignored, but it is assumed to be compatible with the draft 04 JSON Schema specification.

"title": "same text"
"description": "more text"

These keywords are ignored.

"format": "<predefined values>"

The "format" keyword is used to modify either the generated structure or run-time value. See the following information for the supported use of "format".

"type":
"array",
"items": {<JSON Sub-schema>},
"additionalItems": false,
"maxItems":
m
,
"minItems":
n

Multidimensional arrays are supported from mapping level 4.3 or higher, and mixed type arrays are not supported.

"additionalItems" is assumed to be false, and no other value is supported.

If both "minItems" and "maxItems" are present, and they are equal, then the array is treated as fixed cardinality, otherwise it is treated as varying cardinality. See Variable arrays of elements in DFHJS2LS.

"type": "array",
"uniqueItems": true

"uniqueItems" is not supported with JSON arrays. The <JSON Sub-schema> must define a supported "type" , but that "type" cannot be "array" . This is a restriction on the language structure generated.

"type": "object",
"additionalProperties": false,
"properties": { [ "<element name>": {<JSON Sub-schema>} [,] ]* }
"required": [ [ "<element name>" [,] ]* ]

The only form of JSON object currently supported is a fixed set of named elements.

This will generate a structure (or sub-structure) using the element names.

"additionalProperties" is assumed to be false if a value is not set in the ADDITIONAL-PROPERTIES-DEFAULT parameter.

Any element in the "properties" object is considered "optional" if it is not in the "required" array or if no "required" array exists. An "optional" element is given a variable ordinality of zero to X; where X is either 1 or the maximum number of items in the array, where that item is defined as an array. See Variable arrays of elements in DFHJS2LS.

"type": "object",
"additionalProperties": true
The object is mapped as in the previous example, with additional fields that support additional properties. The additionalProperties property is assumed to be false if not set in the ADDITIONAL-PROPERTIES-DEFAULT parameter.

If enabled, space is allocated up to the value specified in the ADDITIONAL-PROPERTIES-MAX parameter. The number of characters in each space is set by the ADDITIONAL-PROPERTIES-SIZE parameter. Each individual property is mapped to a PIC X(z) field where z is defined by the ADDITIONAL-PROPERTIES-SIZE parameter. If the value of ADDITIONAL-PROPERTIES-MAX is greater than 0 then the properties are mapped in an equivalent fashion to that of an array with maxItems set.

Note: There are several ways to configure JSON support in CICS, including use of z/OS Connect for CICS. If you are using the older CICS Java Pipeline technology, Additional Properties are only supported if the com.ibm.cics.json.enableAxis2Handlers JVM system property is not set to true.
"type": "object",
"maxProperties": m,
"minProperties": n,
"patternProperties": {},
"dependencies":

None of these keywords are supported with JSON objects.


"type":"string"
"maxLength":
m
"pattern": "regular expression>",
"minLength":
l

char[ z ]

where the value of z is based on m , but dependent on the settings of the CHAR-VARYING parameter.

m is based on the "maxLength" keyword and treated as fixed length string.

"pattern" and "minLength" restrictions are passed through to the language structure only as a comment.


"type":"string"
"maxLength":
m

When CCSID=1200 at mapping level 4.0 and higher:

WIDECHAR( z )

where the value of z is based on m , but dependent on the settings of the CHAR-VARYING parameter.

m is based on the "maxLength " keyword and treated as fixed length string.

"*name*":{ 
"type":"string",
   "format":"date-time"
}

FIXED DECIMAL (15,0)

All supported when DATETIME=PACKED15

"*name*":{ 
"type":"string",
   "format":"uri"
}

CHAR( m )

where m is based on the "maxLength" keyword and treated as fixed length string.

When CCSID=1200 at mapping level 4.0 and higher:

WIDECHAR( m )

where m is based on the "maxLength" keyword and treated as fixed length string.

"*name*":{ 
"type":"string",
   "format":"base64Binary"
}

CHAR( m )

where m is based on the "maxLength" keyword.

"*name*":{ 
"type":"string",
   "format":"hexBinary"
}

CHAR( m )

where m is based on the "maxLength" keyword.

"*name*":{ 
"type":"string",
   "format":"<predefined>"
}

CHAR( m ) where m is based on the "maxLength" keyword and treated as a fixed length string, and <predefined> is one of: email , hostname , ipv4 or ipv6. A relevant "pattern" is passed to the comment.

When CCSID=1200 at mapping level 4.0 and higher:

WIDECHAR( m )

where  m  is based on the "maxLength"  keyword and treated as fixed length string, and where  <predefined>  is one of:  emailhostnameipv4 , or  ipv6 . A relevant "pattern" is used and passed to the comment.

"type":"boolean"
Mapping level 1.1 and lower:
Enterprise PL/I
SIGNED FIXED BINARY (7)
Other PL/I
FIXED BINARY (7)
Mapping level 1.2 and higher:
Enterprise PL/I
BIT(7)
BIT(1)
Other PL/I
BIT(7)
BIT(1)

where BIT(7) is provided for alignment and BIT(1) contains the Boolean mapped value.

"type": "integer",
"exclusiveMaximum": true,
"exclusiveMinimum": true,
"multipleOf": n

"exclusiveMaximum" and "exclusiveMinimum" restrictions are passed to the language structure only as a comment.

"multipleOf" is ignored.

"type":"integer",
minimum:-128,
maximum:127
Enterprise PL/I
SIGNED FIXED BINARY (7)
Other PL/I
FIXED BINARY (7)
"type":"integer",
minimum:0,
maximum:255
Enterprise PL/I
UNSIGNED FIXED BINARY (8)
Other PL/I
FIXED BINARY (8)
"type":"integer",
minimum:-32768,
maximum:32767
Enterprise PL/I
SIGNED FIXED BINARY (15)
Other PL/I
FIXED BINARY (15)
"type":"integer",
minimum:0,
maximum:65535
Enterprise PL/I
UNSIGNED FIXED BINARY (16)
Other PL/I
FIXED BINARY (16)
"type":"integer",
minimum:-2147483648,
maximum:2147483647
Enterprise PL/I
SIGNED FIXED BINARY (31)
Other PL/I
FIXED BINARY (31)
"type":"integer",
minimum:0,
maximum:4294967295
Mapping level 1.1 and lower:
Enterprise PL/I
UNSIGNED FIXED BINARY(32)
Mapping level 1.2 and higher:
Enterprise PL/I
CHAR( y )

where y is a fixed length that is less than 16 MB.

All mapping levels:
Other PL/I
BIT(64)
"type":"integer",
minimum:-9223372036854775808,
maximum:9223372036854775807
Mapping level 1.1 and lower:
Enterprise PL/I
SIGNED FIXED BINARY(63)
Note: The LIMITS compiler directive might affect how the PL/I compiler interprets this field. CICS expects the field to be of the declared size, but the compiler might optimize the field into a smaller space, which can result in a mismatch. To avoid such problems, use the LIMITS(FIXEDBIN(63)) compile-time option.
Mapping level 1.2 and higher:
Enterprise PL/I
CHAR( y )

where y is a fixed length that is less than 16 MB.

All mapping levels:
Other PL/I
BIT(64)
"type":"integer",
minimum:0,
maximum:18446744073709551615
Mapping level 1.1 and lower:
Enterprise PL/I
UNSIGNED FIXED BINARY(64)
Note: The LIMITS compiler directive might affect how the PL/I compiler interprets this field. CICS expects the field to be of the declared size, but the compiler might optimize the field into a smaller space, which can result in a mismatch. To avoid such problems, use the LIMITS(FIXEDBIN(63)) compile-time option.
Mapping level 1.2 and higher:
Enterprise PL/I
CHAR( y )

where y is a fixed length that is less than 16 MB.

Other PL/I
BIT(64)
"type":"number"
"description":"decimal"
FIXED DECIMAL( n , m )
"type":"number"
"description":"float"
Mapping levels 1.0 and 1.1:
  • CHAR(32)
Mapping level 1.2 and higher:
Enterprise PL/I
DECIMAL FLOAT(6) HEXADEC
Other PL/I
DECIMAL FLOAT(6)
Note: The IBM® Hexadecimal Floating Point (HFP) data representation is not exactly the same as the IEEE-754-1985 representation used for JSON. Some values may not convert exactly from one representation to the other. Some extremely large or small values might not be valid for float data types. Some values may lose precision when converted to or from HFP representation. If precise conversions are important, consider replacing use of DECIMAL FLOAT data types with fixed precision alternatives.
"type":"number"
"description":"double"
Mapping levels 1.0 and 1.1:
  • CHAR(32)
Mapping level 1.2 and higher:
Enterprise PL/I
DECIMAL FLOAT(16) HEXADEC
Other PL/I
DECIMAL FLOAT(16)
Note: The IBM Hexadecimal Floating Point (HFP) data representation is not exactly the same as the IEEE-754-1985 representation used for JSON. Some values may not convert exactly from one representation to the other. Some extremely large or small values might not be valid for float data types. Some values may lose precision when converted to or from HFP representation. If precise conversions are important, consider replacing use of DECIMAL FLOAT data types with fixed precision alternatives.

oneOf: [ { "properties": { "A": {...} } } ,
    { "properties": { "B": {...} } } ]
anyOf: [ { "properties": { "A": {...} } } ,
    { "properties": { "B": {...} } } ]
allOf: [ { "properties": { "A": {...} } } ,
    { "properties": { "B": {...} } } ]

The logical paths through the array of options are merged together as though a single Object had been defined of type { "properties": { "A":..., "B":... } }. Each of the JSON properties is treated as optional. If the sub-options contain conflicting definitions for the same property name, an error message is issued; for example, if a single property is defined as both a String (in path A) and an Object (in path B), then such a definition is not supported and will result in an error message.

It is possible for a JSON schema to define complex logical structures; however, the subtleties implied in the complex logical structures might be lost in the mapping to a language structure. The transformation process does not attempt to enforce the combinatorial rules from the schema; it only interacts with the language structure fields that indicate whether a given JSON property is present or absent.

If the sub-options contain compatible definitions for the same property name, DFHJS2LS attempts to merge the associated pattern of constraints, though some subtleties might be lost in the process. For example, assume the following definition:
"A": { "oneOf": [ { "type": "string", "maxLength": 5}, {"type": "string",
      "minLength": 7, "maxLength": 8} ] }
"A" is defined as either a string up to 5 characters long or a string between 7 and 8 characters long. The merged composition might result in mappings to a string between 0 and 8 characters long, without recognizing that length of 6 characters is invalid.

Most scenarios involving logical composition will map to simple language structures, but complicated logical composition might result in compromises during the mapping process. For best results, avoid using logical composition in a JSON schema to define alternative declarations for the same JSON property.

Note: CICS cannot transform integer values greater than the maximum value for a signed long (2^63 - 1) unless they are enclosed within quotes.
Note: Minimum and maximum values specified in the schema for numeric types are used only to map to a PL/I datatype. Data is not validated against these values at runtime.