Variants are dynamic types that can hold values of any other type (Integer, Float, String, Boolean, Objects, etc.). They are useful when the exact type of data is unknown until runtime, such as when processing dynamic API responses or building highly flexible components.
A Variant variable adapts its behavior based on the value it currently holds.
var v: Variant;
v := 10; // Holds an Integer
v := 'Hello'; // Now holds a String
PrintLn(v);
v := 3.14; // Now holds a Float
PrintLn(v); Hello 3.14
You can check the current type of a variant using the VarType function or helper functions like VarIsNumeric.
var v: Variant := 10;
// Check if numeric
if VarIsNumeric(v) then
PrintLn('It is numeric'); It is numeric
Performance & Safety: Variants are significantly slower than strongly-typed variables and bypass many compile-time checks. Use them sparingly, primarily for dynamic data or interoperability.
JSONVariant is a specialized variant optimized for working with JSON data. It supports late-binding, allowing you to access properties using dot notation even if they aren't defined at compile time.
For detailed usage, see JSON Support.
When working with JSON, you can check for field existence using .Defined(), standard truthy/falsy checks, or VarIsClear.
Parenthesis Rule: When calling built-in methods on a JSONVariant (like .Defined() or .Length()), you must use parentheses to distinguish them from potential JSON fields with the same name.
var data := JSON.Parse('{"name": "Alice"}');
// Check if defined
if not data.age.Defined() then
PrintLn('Age is missing');
// Truthy check (undefined behaves like False/Null)
if not data.age then
PrintLn('Age is not set'); Age is missing Age is not set
Variants handle mixed-type comparisons by attempting to convert values to a common type.
var v1: Variant := 10;
var v2: Variant := '10';
if v1 = v2 then
PrintLn('They are equal'); // True, string converted to integer for comparison They are equal