Value
The generic data type used throughout Jetzig is *jetzig.data.Value. This type is designed to work with a large number of inputs, providing a balance between flexibility, ease of use, and standaridization for multiple consumers (for example, *jetzig.data.Value can always be serialized to JSON.
A call to request.data(.object) or request.data(.array) returns a *jetzig.data.Value.
This type is used for Zmpl template values, JSON output, request parameters, cache, store, and background jobs.
pub const Value = union(enum) {
object: Object,
array: Array,
float: Float,
integer: Integer,
boolean: Boolean,
string: String,
datetime: jetzig.DateTime,
null: NullType,
// ...
};
*Value provides a number of member functions that delegate to the relevant underlying data type. This allows you to primarily operate on the *Value type directly, without needing to switch to identify the active field. e.g. Value.get returns null if Value.object is not active.
Member Functions
get
pub fn get(self: *Value, key: []const u8) ?*Value
Returns a *Value when the given key is found in a Value.object. If Value.object is not active, returns null. If key is not found, returns null.
If key is present but was set to null, Value.null is returned. This allows you to switch on the returned value and identify keys that exist but have no value.
For example, request.params() returns a *Value and allows detection of query params that have no value, or a JSON request body with null values:
pub fn index(request: *jetzig.Request) !jetzig.View {
const params = try request.params();
if (params.get("redirect")) |location| {
switch (location.*) {
// Value is `.null` when param is empty, e.g.:
// `http://localhost:8080/redirect?redirect`
.null => return request.redirect("http://www.example.com/", .moved_permanently),
// Value is `.string` when param is present, e.g.:
// `http://localhost:8080/redirect?redirect=https://jetzig.dev/`
.string => |string| return request.redirect(string.value, .moved_permanently),
else => unreachable,
}
} else {
return request.render(.ok);
}
}
getT
pub fn getT(self: *Value, comptime T: ValueType, key: []const u8) ?switch (T) {
.object => *Object,
.array => *Array,
.string => []const u8,
.float => f128,
.integer => i128,
.boolean => bool,
.null => null,
}
Returns the underlying type of the *Value matching the given key. Returns null if a match is found but with the wrong type.
getT can significantly reduce boilerplate by removing the need to switch on Value.
Note that the following example is not identical to the example given for get as it does not detect when the redirect query param is provided but with no value. If this functionality is required, get must be used with switch.
pub fn index(request: *jetzig.Request) !jetzig.View {
const params = try request.params();
if (params.getT(.string, "redirect")) |location| {
return request.redirect(location, .moved_permanently);
} else {
return request.render(.ok);
}
}
coerce
pub fn coerce(self: Value, T: type) ZmplError!ComptimeErasedType(T)
Attempt to coerce a value to any other type. Return an error if no value is provided.
chain
pub fn chain(self: *Value, keys: []const []const u8) ?*Value
Pass an array of []const u8 to recursively fetch values from a nested Object.
Returns null if Value.object is not active or if any of the provided keys are not found.
put
pub fn put(self: *Value, key: []const u8, value: ?*Value) !PutAppend(@TypeOf(value))
Put a given *Value into a Value.object under the fieldname key.
The special values .object and .array return a new object or array inserted into the object at the given key.
All other values return void.
append
pub fn append(self: *Value, value: ?*Value) !void
Appends a *Value to a Value.array. When value is null, Value.null is appended.
The special values .object and .array return a new object or array appended to the array.
All other values return void.
remove
pub fn remove(self: *Value, key: []const u8) bool
Remove the value found at key from the current object tree. Return true if key was found, otherwise false.
pop
pub fn pop(self: *Value) ?*Value
Pop the last value from an array. If the array is empty, return null.
count
pub fn count(self: *Value) usize
Returns the current number of items in a a Value.array or Value.object.
items
pub fn items(self: *Value, comptime selector: IteratorSelector) []switch (selector) {
.array => *Value,
.object => Item,
}
Receives a selector which must be .array or .object.
When selector is .array, returns an array of *Value.
When selector is .object, returns an array of Item:
const Item = struct {
key: []const u8,
value: *Value,
};