JSONOneOf
Specify a record that needs to be serialized or deserialized.
This topic may change, as is in the process of being updated for the Early Access Program. If you find any issues while using the information contained within, please use the Feedback mechanism to let us know what problems you encounter.
Syntax
JSONOneOf
is an optional attribute.
Usage
You can set JSONOneOf
on a record, elements of a record, or a user-defined type to specify elements that need to be serialized or
deserialized. For example, if you have complex data or data that is flexible in how it may be
represented, then you can define the data with a number of schemas and JSONOneOf
to
validate against exactly one of the schemas at runtime.
This attribute represents the oneOf
keyword in the JSON schema property of the
Swagger and OpenAPI specification.
The JSONOneOf
attribute must be used in combination with the JSONSelector attribute.
Example using JSONOneOf
In this example, the JSONOneOf
attribute is set on the input record of the
CreateAccount
function. At a request to the
service, you can choose which member of the createAccountType
record –
id
or name
– to use by setting the _selector
to
the index value of the record member. For example, to specify the name
, in the
client set _selector
to 2 in the statement LET
in._SELECTOR=2
. This specific member must have a JSONSelector
attribute.
In the CreateAccount
function, the CASE
statement tests for the _selector
value.
IMPORT COM
PUBLIC TYPE accountType RECORD
id INTEGER,
name STRING,
date DATETIME YEAR TO SECOND,
age INTEGER,
gender BOOLEAN
END RECORD
PRIVATE DEFINE accounts DYNAMIC ARRAY OF accountType
PUBLIC DEFINE accountError RECORD ATTRIBUTE(WSError = 'account service error')
id INTEGER,
msg STRING
END RECORD
TYPE createAccountType RECORD ATTRIBUTE(JSONOneOf)
_selector INTEGER ATTRIBUTE(JSONSelector),
id INTEGER,
name STRING
END RECORD
FUNCTION CreateAccount(
in createAccountType)
ATTRIBUTE(WSPost, WSPath = "/createaccount")
RETURNS(createAccountType)
DEFINE out createAccountType
DEFINE idx INTEGER
LET out = in
CASE
WHEN in._selector = 1
LET idx = accounts.search("id", in.id)
IF idx > 0 THEN
# raise RESTError with accountError
ELSE
CALL accounts.appendElement()
LET accounts[accounts.getLength()].id = in.id
END IF
WHEN in._selector = 2
LET idx = accounts.search("name", in.name)
# ... function code ...
END CASE
RETURN out
END FUNCTION
In the OpenAPI documentation, the GWS engine exposes the oneOf
property in the
schema
for the record elements defined with JSONOneOf
. In the
following sample schema, a request to the operation to create an account can choose to send the
record for the id or name.
Example 2: using JSONOneOf with JSONRequired
In this example, the use of the JSONRequired
attribute in addition to the
JSONOneOf
attribute is important to validate the schemas. In the
complexType
record, there are three sub-records each with the
JSONOneOf
attribute. Each sub-record has a required member set with the
JSONRequired
attribute. The effect of this required member is that it allows the
schemas to be validated.
In JSON schema, there is a default to allowing additional properties – properties
that do not correspond to any property name – which has the effect of allowing schemas to be
validated with any properties. Therefore, in our example (with JSONOneOf
alone) no
schema would be invalid, since they would all be valid.
JSONRequired
in the validation process, the JSON schema checks that the
required property has been received; otherwise, the schema will be invalid and will be eliminated.
In the end, according to the oneOf
requirement, there must remain only one valid
schema in all the possible schemas.For the moment, we have not yet implemented support for additional
properties, but later we will introduce the WSAdditionalProperties
attribute
to allow you to handle this by turning off additional properties. In the meantime, the
recommendation is to use the JSONRequired
attribute instead.
For more information on properties and additional properties, go to the JSON Schema (external link) object page and search for additional properties.
# In this example, a property with attribute JSONRequired is mandatory
# Otherwise, all schemas will be valid and oneOf can only accept one valid schema
TYPE complexType RECORD ATTRIBUTE(JSONOneOf)
_selector INTEGER ATTRIBUTE(JSONSelector),
accountById RECORD
id INTEGER ATTRIBUTE(JSONRequired),
birthday DATE,
gender BOOLEAN
END RECORD,
accountByname RECORD
name STRING ATTRIBUTE(JSONRequired),
birthday DATE,
gender BOOLEAN
END RECORD,
accountBydate RECORD
date DATETIME YEAR TO SECOND ATTRIBUTE(JSONRequired),
birthday DATE,
gender BOOLEAN
END RECORD
END RECORD
FUNCTION echoComplexType(
in complexType)
ATTRIBUTE(WSPost, WSPath = "/echoComplexType")
RETURNS(complexType)
DEFINE out complexType
LET out = in
DISPLAY out._selector
CASE
WHEN out._selector == 2
DISPLAY "This is the schema 1 with id required property: ",
out.accountById.id
WHEN out._selector == 3
DISPLAY "This is the schema 2 with STRING value: ",
out.accountByName.name
WHEN out._selector == 4
DISPLAY "This is the schema 3 with DATE value: ",
out.accountBydate.date
END CASE
RETURN out
END FUNCTION
In the OpenAPI documentation, the GWS creates the schema
that has the
oneOf
property and each object in the array it defines the
required
property for its object.