Key Syntax and Semantics

Dayforce Integration Studio Administrator Guide

Version
R2025.1.0
Key Syntax and Semantics

IDL is largely composed of the following key concepts: blocks, arrays, operators, conditional expressions, and function pipelines. Additionally, single line and multi-line comments are supported using // and /*…*/, respectively.

Blocks: Chunks of data organized in key-value pairs, contained within curly braces {…} and are analogous to JSON objects. Some blocks are named, such as the mapping block within the IDL Mapping file, while unnamed blocks are considered “anonymous”. An expression configured for a specific field is considered an anonymous block.

Arrays: Lists of objects that are typically related in some way. For example, one of the arrays included in the Bulk Employee API data source is titled “WorkAssignments” and each object in the array contains an assortment of fields which, together, represent one work assignment. If an employee has three work assignments, the WorkAssignments array would have three objects, each with the same set of fields but different values, per the different work assignments on the employee record in Dayforce. Arrays in IDL are analogous to arrays in JSON.

Operators: Enable basic mathematical operations and logical operations that can link criteria in conditional expressions.

Types of operators in IDL
Types Operators
Arithmetic
  • Addition (+)
  • Subtraction (-)
  • Multiplication (*)
  • Division (/)

Note: Standard operator precedence applies (PEMDAS).

Logical
  • And (&&)
  • Or (||)
  • Unary not (!)

Note: Standard Boolean operator precedence applies (Not > And > Or).

Conditional expressions: Allow testing conditions by using an if / else if / else branching structure. All branches must return a value. In the example below, the Job field includes a conditional expression which returns the BankName if it exists; otherwise, it returns a static value of UnknownBank.

Copy
mapping {
    Root = map(source.Data, srcData => {
        EmployeeNumber = srcData.EmployeeNumber ?? nil;
        Job = if is_material(srcData.DirectDeposits.Items.BankName ?? nil) {
            srcData.DirectDeposits.Items.BankName ?? nil
        } else {
            "UnknownBank"
        };
    });
}

Similarly, a conditional expression can validate two fields that are joined by the And (&&) logical operator before returning a result:

Copy
mapping {
    Root = map(source.Data, srcData => {
        EmployeeNumber = srcData.EmployeeNumber ?? nil);
        Job = if is_material(srcData. DirectDeposits.Items.BankName ?? nil) && !is_material(srcData.DirectDeposits.Items.EffectiveEnd ?? nil) {
        } else {
            "UnknownBank"
        };
    });
}

Function pipelines: Replace traditional function notation for reading IDL expressions from left to right.

Traditional function notation is read from inside out. For example, f(g(h(x))) is read in this order: perform operation h on value x, then perform operation g on the result of operation h, then perform operation f on the result of operation g.

However, IDL functions can be fed into each other using pipelines, which are composed of a pipe symbol and an angled bracket: |>. Before the pipe, you must have either a value or a function that returns a value. The function after the pipe must accept the returned value as input.

Example: Assuming January 24, 2023 is the HireDate, the following two expressions evaluate to the same result:

Copy
foo {
    bar = date_add(HireDate, 2, "days")
        |> format_date("MM/dd/yyyy"); // => "01/26/2023"
}

Instead of including HireDate as input to the date_add function, we can define the date using the date function, then pass the result as input to the date_add function using function pipelines:

Copy
foo {
    bar = date(2023, 1, 24)
        |> date_add(2, "days")
        |> format_date("MM/dd/yyyy"); // => "01/26/2023"
}

Unknown, Empty, and Missing Values

Values included in IDL functions can be known, unknown, empty, or missing. IDL handles each value differently.

Known values are easy; when passed into a valid IDL, Integration Studio generates the expected result.

Unknown values are called NIL. NULL is traditionally used in place of an unknown value in computing systems. NIL serves the same purpose in IDL. NIL values fed into functions will have a nil (null) result. For example, the following expression would return a nil value if the SeniorityDate field is unknown in Dayforce:

Copy

    date_add(SeniorityDate, 10, "years");

Values that are also containers, such as arrays and strings, can be empty. For example, an employee with no direct deposit records in Dayforce would have an empty <DirectDeposit> array in the final output for the example outbound integration as follows:

Direct Deposit Array example.

Unlike empty values and unknown values (NIL and NULL), a missing value doesn’t exist at all. For example, if an employee in Dayforce has no middle name, the following function call would result in the field bar being removed from the output:

Copy
foo = EmployeeNumber
bar = string_concat(FirstName, MiddleName, LastName);

If a function is missing a value, that missing value isn’t included in any results of that function. It’s also omitted from any other functions that use the original missing value.

If a value might be missing in the source, but the field should remain in the output regardless, or if other pieces of the expression must execute despite a missing value, the potentially missing value can be wrapped in a coalesce function, which either returns the value if it exists or returns the default value provided:

Copy
foo = coalesce(EmployeeNumber, ReferenceCode)
bar = coalesce(string_concat(FirstName, MiddleName, LastName), nil);

Aggregations

Aggregations allow counts of records included in the integration, mainly for reporting counts of specific elements within the integration in headers and footers. For example, the IDL configuration below uses the count function to report on employee records, dependent records, as well as overall records:

Copy
mapping {
    Root = map(source.Data, emp => {
        id = emp.XRefCode;
        name = emp.FullName;
        @employeeCount = count();
        @recordCount = count();
        dependents = map(emp.Dependents, dep => {
            name = dep.FullName;
            @dependentCount = count();
            @recordCount = count();
        });
        numberofEmployees = @employeeCount;
        numberofDependents = @dependentCount;
        totalNumberOfRecords = @recordCount;
    });
}