JSONAllOf

Combine multiple record schemas into a single type using the JSONAllOf attribute in Genero BDL.

Syntax

JSONAllOf is an optional attribute that allows you to combine multiple record types into a single schema, following the JSON Schema allOf keyword.

Important:

This serializer-specific attribute is supported only by json.Serializer and does not work with util.JSON.

Usage

The JSONAllOf attribute enables you to define a type that merges the properties of several record types. This is useful for composing complex types from reusable components. The resulting type will include all unique properties from the specified record types.

There is a new fglrestful option that enables you to preserve the integrity of allof schemas. By using the --no-merge-allof option, you can disable the merging of properties in schemas where the JSONAllOf attribute is applied.

BDL Example

This sample illustrates how to apply the JSONAllOf and JSONRequired attributes to define composite and mandatory properties in JSON schemas.

IMPORT com

DEFINE g_nextId INTEGER = 1
DEFINE Employees DYNAMIC ARRAY OF Employee

TYPE Address RECORD
    street STRING,
    city STRING ATTRIBUTE(JSONRequired)
END RECORD

TYPE Person RECORD
    id INTEGER,
    name STRING ATTRIBUTE(JSONRequired),
    age INTEGER
END RECORD

TYPE Employee RECORD ATTRIBUTE(JSONAllOf)
    employeeInfo Person,
    employeeLocation Address
END RECORD

FUNCTION getEmployee(
    id INTEGER ATTRIBUTE(WSParam))
    ATTRIBUTE(WSGet, WSPath = "/getEmployee/{id}")
    RETURNS(Employee)
    DEFINE emp Employee
    DEFINE ind INTEGER
    DEFINE foundId BOOLEAN

    IF Employees.getLength() = 0 THEN
        LET Employees[1].employeeInfo.id = 1
        LET Employees[1].employeeInfo.name = "Alice"
        LET Employees[1].employeeInfo.age = 30
        LET Employees[1].employeeLocation.street = "Rue Montesquieu"
        LET Employees[1].employeeLocation.city = "Paris"
    END IF

    FOR ind = 1 TO Employees.getLength()
        IF Employees[ind].employeeInfo.id = id THEN
            LET emp = Employees[ind]
            LET foundId = TRUE
            EXIT FOR
        END IF
    END FOR

    IF NOT foundId THEN
        CALL com.WebServiceEngine.SetRestError(404, "Employee not found")
    END IF

    RETURN emp
END FUNCTION

FUNCTION addEmployee(
    empIn Employee)
    ATTRIBUTE(WSPost, WSPath = "/addEmployee", WSRetCode = '2XX')
    RETURNS(Employee)
    DEFINE empOut Employee

    # Generate a dummy ID
    LET g_nextId = g_nextId + 1
    LET empIn.employeeInfo.id = g_nextId
    LET Employees[Employees.getLength() + 1] = empIn

    DISPLAY "getlength: ", Employees.getLength()

    # Log server
    DISPLAY SFMT("Adding employee '%1' with id: %2",
        Employees[Employees.getLength()].employeeInfo.name,
        Employees[Employees.getLength()].employeeInfo.id)

    CALL com.WebServiceEngine.SetRestStatus(201)

    LET empOut = empIn
    RETURN empOut
END FUNCTION

Where:

  1. The JSONAllOf attribute is set on the Employee TYPE definition. Note: this attribute can only be applied to TYPE definitions.
  2. Two separate records, Person and Address, are defined and combined into Employee at runtime. Each record has unique field names, ensuring compatibility with JSON Schema allOf semantics.
  3. JSONRequired is used with name in Person and city in Address to enforce these mandatory fields.

Compilation and validation rules

  1. Restriction to TYPE definitions: JSONAllOf can only be used in TYPE definitions.

  2. Mutual exclusion: JSONAllOf cannot be used with JSONOneOf or JSONAdditionalProperties on the same type. Using JSONAllOf with JSONOneOf or JSONAdditionalProperties will result in error-9150

  3. Restriction to RECORD types: Only RECORD types are allowed as subschemas. Using JSONAllOf with unsupported types or functions will result in error-9153

  4. Unique property names: All property names in the combined records must be unique. Using JSONAllOf with duplicate properties will result in error-9154

  5. No nested JSONAllOf: Nesting JSONAllOf attributes within another JSONAllOf structure is not permitted, as it can create ambiguity and will result in error-9155.