Dynamic#
The Dynamic global is your escape hatch for working with schema-free data. When you need to deal with JSON-like values that don't fit neatly into a record definition -- API responses, user-provided payloads, configuration blobs -- this is where you go.
Creating Dynamic Values#
Convert typed values into dynamic:
Function
Description
Returns
Dynamic.dyn(bool)
Create from boolean
dynamic
Dynamic.dyn(int)
Create from integer
dynamic
Dynamic.dyn(long)
Create from long
dynamic
Dynamic.dyn(double)
Create from double
dynamic
Dynamic.dyn(string)
Create from string
dynamic
dynamic d1 = Dynamic.dyn(true); // true
dynamic d2 = Dynamic.dyn(42); // 42
dynamic d3 = Dynamic.dyn(3.14); // 3.14
dynamic d4 = Dynamic.dyn("hello"); // "hello"
Extension methods work too:
dynamic d = (42).dyn(); // 42
dynamic s = "hello".dyn(); // "hello"
Parsing#
Function
Description
Returns
Dynamic.parse(str)
Parse JSON string
maybe<dynamic>
Dynamic.to_dyn(str)
Parse JSON string (alias)
maybe<dynamic>
maybe<dynamic> parsed = Dynamic.parse("{\"name\": \"Alice\", \"age\": 30}");
if (parsed as data) {
// use data
}
Pull typed values out of dynamic data:
Function / Method
Description
Returns
Dynamic.str(d)
Extract as string
maybe<string>
Dynamic.i(d)
Extract as int
maybe<int>
Dynamic.l(d)
Extract as long
maybe<long>
Dynamic.d(d)
Extract as double
maybe<double>
Dynamic.b(d)
Extract as boolean
maybe<bool>
dynamic data = @dynamic 42;
maybe<int> val = Dynamic.i(data); // 42
maybe<string> str = Dynamic.str(data); // empty (not a string)
When you have a dynamic object and want to pull out a specific field, there are overloads that take a field name -- and versions with defaults so you don't have to deal with maybe when you know what you want:
Function
Description
Returns
Dynamic.str(d, field)
Extract field as string
maybe<string>
Dynamic.str(d, field, default)
Extract with default
string
Dynamic.i(d, field)
Extract field as int
maybe<int>
Dynamic.i(d, field, default)
Extract with default
int
Dynamic.l(d, field)
Extract field as long
maybe<long>
Dynamic.l(d, field, default)
Extract with default
long
Dynamic.d(d, field)
Extract field as double
maybe<double>
Dynamic.d(d, field, default)
Extract with default
double
Dynamic.b(d, field)
Extract field as bool
maybe<bool>
Dynamic.b(d, field, default)
Extract with default
bool
Dynamic.date(d, field)
Extract field as date
maybe<date>
Dynamic.datetime(d, field)
Extract field as datetime
maybe<datetime>
dynamic user = @dynamic {"name": "Alice", "age": 30, "active": true};
maybe<string> name = Dynamic.str(user, "name"); // "Alice"
string safe_name = Dynamic.str(user, "name", "?"); // "Alice"
maybe<int> age = Dynamic.i(user, "age"); // 30
int safe_age = Dynamic.i(user, "age", 0); // 30
maybe<bool> active = Dynamic.b(user, "active"); // true
Type Checking#
Sometimes you need to know what kind of value you're dealing with:
Function
Description
Returns
Dynamic.is_array(d)
Check if value is an array
bool
Dynamic.is_object(d)
Check if value is an object
bool
Dynamic.is_string(d)
Check if value is a string
bool
Dynamic.is_number(d)
Check if value is a number
bool
Dynamic.is_bool(d)
Check if value is a boolean
bool
Dynamic.is_null(d, fld)
Check if field is null
maybe<bool>
dynamic arr = @dynamic [1, 2, 3];
dynamic obj = @dynamic {"x": 1};
bool is_arr = Dynamic.is_array(arr); // true
bool is_obj = Dynamic.is_object(obj); // true
Structure Inspection#
Function
Description
Returns
Dynamic.size(d)
Get array length or object size
maybe<int>
Dynamic.has(d, field)
Check if field exists
bool
Dynamic.keys(d)
Get list of object keys
list<string>
dynamic obj = @dynamic {"a": 1, "b": 2, "c": 3};
maybe<int> sz = Dynamic.size(obj); // 3
bool has_a = Dynamic.has(obj, "a"); // true
bool has_z = Dynamic.has(obj, "z"); // false
list<string> ks = Dynamic.keys(obj); // ["a", "b", "c"]
Access and Navigation#
Function
Description
Returns
Dynamic.atIndex(d, index)
Access array element by index
dynamic
Dynamic.atField(d, field)
Access object field by name
dynamic
dynamic arr = @dynamic [10, 20, 30];
dynamic second = Dynamic.atIndex(arr, 1); // 20
dynamic obj = @dynamic {"x": 42};
dynamic x_val = Dynamic.atField(obj, "x"); // 42
Function
Description
Returns
Dynamic.merge(target, patch)
Merge two dynamic objects
dynamic
Dynamic.to_str(d)
Convert to JSON string
string
Dynamic.arr(items)
Convert list to dynamic array
dynamic
dynamic base = @dynamic {"a": 1, "b": 2};
dynamic patch = @dynamic {"b": 3, "c": 4};
dynamic merged = Dynamic.merge(base, patch); // {"a":1,"b":3,"c":4}
string json = Dynamic.to_str(merged); // "{\"a\":1,\"b\":3,\"c\":4}"
Json Global#
The Json global works with the json type -- a structured variant of dynamic that supports field navigation directly.
Function
Description
Returns
Json.parse(str)
Parse JSON string
maybe<json>
Json.parsen(str)
Parse JSON (null on failure)
json
maybe<json> j = Json.parse("{\"x\": 123}");
// Field navigation on json
json data = Json.parsen("[42]");
formula first = data[0]; // 42
Common Patterns#
Processing API Responses#
procedure handle_response(dynamic response) {
string status = Dynamic.str(response, "status", "unknown");
if (status == "success") {
maybe<int> count = Dynamic.i(response, "count");
if (count as c) {
// process count
}
}
}
Building Dynamic Objects#
procedure build_payload() -> dynamic {
return Dynamic.merge(
@dynamic {"type": "event"},
@dynamic {"timestamp": Time.now()}
);
}
Method Summary#
Function
Returns
Description
Dynamic.dyn(value)
dynamic
Create from typed value
Dynamic.parse(str)
maybe<dynamic>
Parse JSON string
Dynamic.to_dyn(str)
maybe<dynamic>
Parse JSON string (alias)
Dynamic.str(d) / .str(d,f)
maybe<string>
Extract string
Dynamic.i(d) / .i(d,f)
maybe<int>
Extract integer
Dynamic.l(d) / .l(d,f)
maybe<long>
Extract long
Dynamic.d(d) / .d(d,f)
maybe<double>
Extract double
Dynamic.b(d) / .b(d,f)
maybe<bool>
Extract boolean
Dynamic.is_array(d)
bool
Type check: array
Dynamic.is_object(d)
bool
Type check: object
Dynamic.is_string(d)
bool
Type check: string
Dynamic.is_number(d)
bool
Type check: number
Dynamic.is_bool(d)
bool
Type check: boolean
Dynamic.is_null(d, field)
maybe<bool>
Check null field
Dynamic.size(d)
maybe<int>
Array/object size
Dynamic.has(d, field)
bool
Check field exists
Dynamic.keys(d)
list<string>
Object keys
Dynamic.atIndex(d, i)
dynamic
Array element access
Dynamic.atField(d, f)
dynamic
Object field access
Dynamic.merge(a, b)
dynamic
Merge objects
Dynamic.to_str(d)
string
Convert to JSON string
Dynamic.arr(list)
dynamic
List to dynamic array
Json.parse(str)
maybe<json>
Parse to json type
Json.parsen(str)
json
Parse (null on failure)