# Advanced Attribute Data Types

reviewed: 22 March 2025

We have seen basic datatypes for attributes in action. An attribute can however also have more advanced datatypes. It is important to understand that each CaseMaster datatype maps onto the most meaningful RDBMS database and that some of the advanced datatypes are designed mainly for attributes that do not have a column.

Expression

The simplest of the advanced datatype is the expression. This is stored in the database as a string.

Attributes of type expression are designed to store CaseMaster expressions and are often used as part of reference data based business rules. Somewhere in the system we do an eval() to evaluate the expression.

The following is a typical example of an expression.

    active: <@bo/attribute/expression
        label: <@mlText 'Active'>
        column: 'active'
    >

CaseMaster will only accept a syntax-correct expression as input. This is not to say that the expression will always evaluate correctly. Take for example e following expression:

    mul( [price], div( bo.attr( [globalSettings], 'discount' ), 100 ) )

The syntax of this expression is correct. However, it can only be evaluated successfully when the variable price has a value and the BO globalSettings has been loaded.

The following method shows how the expression attribute can be used:

function isActive()
    return or(
        isNull( bo.attr( [_me], 'active' ) ),
        eval( bo.attr( [_me], 'active' ) )
    )
end-function

BO

Attributes of datatype BO (typically) do not have a column and are often used as dynamic attributes.

Attributes of datatype BO are often for advanced use and can be useful for performance.

Assume a BO orderLine which has a foreign key to order which, in turn, has a foreign key to client.

The following could be a useful dynamic attribute of the entity orderLine:

    _client: <@bo/attribute/dynamic
        label: 'Client'
        datatype: datatype.BusinessObject
        dynamicValue: $script(
            bo.loadFK( [_me], 'order', 'client' ),
            bo.loadFK( [order], 'client' )
        )
    >

In methods of orderLine you can now refer to something like bo.attr( bo.attr( [_me], '_client' ), 'address ). What happens is:

  • The function script() eveluates all functions of the parameter list and returns the value of the last parameter
  • A dynamic attribute is cached so order and client are only loaded once
  • Because the attribute _client is of type datatype.BusinessObject, the value of the attribute can be used as a handle to a BO (and thus the first parameter to the bo.attr() function)

JSON

The datatype JSON can be very useful if you want to store JSON in the database. A good example of the JSON datatype is the multi-language attribute (see here).

When you have an attribute with datatype JSON, two additional tags are relevant:

  • jsonFormattedPath
  • jsonOrderByPath

jsonFormattedPath

The value of the tag jsonFormattedPath is used when we request bo.attrFormatted() of an attribute of type JSON.

A special case is when the first character of jsonFormattedPath is a @. In this case we will assume that the JSON stored in the database can be mapped onto a qualifier. The use of this feature is highly advanced and beyond the scope of this documentation.

    _url: <@bo/attribute/json
        label: 'URL'
        jsonFormattedPath: '@url'
    >

If the first character of the tag is not a '@', the value is treated as an JSON Path query that will be used to retrieve a value from JSON and return that as the formatted value.

Take the following example:

    _orderJSON: <@bo/attribute/json
        label: 'Order JSON'
        jsonOrderByPath: '//data/reference'
        jsonFormattedPath: '//data/reference'
    >

and assume the JSON stored would be something like:

{
    "data" : {
        "reference" : "AB8788776-H778",
        "orderDate" : "12/4/2025",
        "totalAmount" : 25.12
    }
}

jsonOrderByPath

The tag jsonOrderByPath is somewhat similar to jsonFormattedPath but is used to allow you to sort by a JSON attribute in queries. jsonOrderByPath Does not support the '@' feature and is thus always considered a valid JSON Path query.

This feature is natively supported for the following database managers:

  • SQL Server (version must support JSON_VALUE)
  • MySQL (version must support JSON_VALUE)
  • Oracle (version must support JSON_VALUE)
  • SQLLite (version must support json_extract)
  • Postgress (version must support json_extract_path)
  • DB2 (version must support JSON_VAL)

It is possible to define a bespoke JSON stored procedure when the native JSON function is not supported. The following configuration settings would for example work for old SQL Server versions:

    dataSources: <@configuration/dataSources
        primary: <@configuration/dataSource/MsSql
            type: dataSourceType.primary
            connectionString: 'Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=oldDatabase;Data Source=dbserver'
            jsonvaluefunction: 'dbo.json_Value'
        >
    >

Property Bag

Attributes of type property bag are, just like BO, not designed for direct storage in the database. As with BO, usage is typically highly advanced and beyond the scope of this documentation.

<End of document>