JSONOneOf

Specify a record that needs to be serialized or deserialized.

Warning:

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.

The output shown is from the Firefox® browser, which converts JSON to human readable format. The output may vary depending on your browser.
Figure: Sample JSON schema with oneOf property

Image from the OpenAPI document showing the "one of'"JSON schema property

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.

With 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.
Important: Additional properties support in development

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.

The output shown is from the Firefox browser, which converts JSON to human readable format. The output may vary depending on your browser.
Figure: Sample JSON schema with oneOf and required properties

Image from the OpenAPI document showing the "one of'" and required JSON schema properties