Skip to content

Array Operations ​

zon.zig supports working with ZON arrays, including reading, creating, and appending to arrays.

Reading Arrays ​

Get Array Length ​

zig
const source =
    \\.{
    \\    .paths = .{
    \\        "build.zig",
    \\        "src",
    \\        "README.md",
    \\    },
    \\}
;

var doc = try zon.parse(allocator, source);
defer doc.deinit();

const len = doc.arrayLen("paths"); // 3

Get Array Elements ​

zig
// Get string at specific index
const first = doc.getArrayString("paths", 0); // "build.zig"
const second = doc.getArrayString("paths", 1); // "src"

// Iterate through array
var i: usize = 0;
while (doc.getArrayString("paths", i)) |path| : (i += 1) {
    std.debug.print("Path: {s}\n", .{path});
}

Get Element as Value ​

zig
// Get raw Value pointer
const elem = doc.getArrayElement("paths", 0);
if (elem) |e| {
    if (e.asString()) |s| {
        std.debug.print("String: {s}\n", .{s});
    }
}

Creating Arrays ​

Create Empty Array ​

zig
var doc = zon.create(allocator);
defer doc.deinit();

// Create empty array at path
try doc.setArray("items");

Append to Array ​

zig
// Append strings
try doc.appendToArray("items", "first");
try doc.appendToArray("items", "second");
try doc.appendToArray("items", "third");

// Append integers
try doc.setArray("numbers");
try doc.appendIntToArray("numbers", 1);
try doc.appendIntToArray("numbers", 2);
try doc.appendIntToArray("numbers", 3);

// Insert at specific index
try doc.insertStringIntoArray("items", 0, "zeroth");

// Remove from specific index
_ = doc.removeFromArray("items", 1);

Advanced Array Operations ​

Finding Elements ​

Use indexOf to find the first occurrence of a string value in an array:

zig
if (doc.indexOf("items", "second")) |index| {
    std.debug.print("Found 'second' at index {d}\n", .{index});
}

Counting Items at Path ​

countAt works on both objects (counting keys) and arrays (counting elements):

zig
const count = doc.countAt("items");
const count = doc.countAt("items");
std.debug.print("Array has {d} items\n", .{count});

Pop, Shift, Unshift ​

New in v0.0.5, you can use stack/queue operations:

zig
// Remove last element
if (doc.popFromArray("items")) |val| {
    defer val.deinit(allocator); // Don't forget to free!
    // use val...
}

// Remove first element
if (doc.shiftArray("items")) |val| {
    defer val.deinit(allocator);
}

// Add to beginning
try doc.unshiftArray("items", .{ .string = try allocator.dupe(u8, "start") });

Practical Example ​

zig
const std = @import("std");
const zon = @import("zon");

pub fn main() !void {
    var gpa = std.heap.DebugAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    zon.disableUpdateCheck();

    // Parse build.zig.zon style array
    const source =
        \\.{
        \\    .paths = .{
        \\        "build.zig",
        \\        "build.zig.zon",
        \\    },
        \\}
    ;

    var doc = try zon.parse(allocator, source);
    defer doc.deinit();

    // Read existing array
    std.debug.print("Original paths ({d} items):\n", .{doc.arrayLen("paths").?});
    var i: usize = 0;
    while (doc.getArrayString("paths", i)) |path| : (i += 1) {
        std.debug.print("  - {s}\n", .{path});
    }

    // Append new items
    try doc.appendToArray("paths", "src");
    try doc.appendToArray("paths", "README.md");
    try doc.appendToArray("paths", "LICENSE");

    std.debug.print("\nAfter appending ({d} items):\n", .{doc.arrayLen("paths").?});
    i = 0;
    while (doc.getArrayString("paths", i)) |path| : (i += 1) {
        std.debug.print("  - {s}\n", .{path});
    }

    // Create new array
    try doc.setArray("tags");
    try doc.appendToArray("tags", "stable");
    try doc.appendToArray("tags", "0.0.5");

    const output = try doc.toString();
    defer allocator.free(output);
    std.debug.print("\nFinal ZON:\n{s}\n", .{output});
}

build.zig.zon Format ​

zon.zig fully supports the build.zig.zon array format:

zig
.{
    .name = .my_package,
    .version = "0.1.0",
    .paths = .{
        "build.zig",
        "build.zig.zon",
        "src",
    },
}

Read with:

zig
const name = doc.getString("name"); // "my_package"
const paths_len = doc.arrayLen("paths"); // 3
const first_path = doc.getArrayString("paths", 0); // "build.zig"

Array Sorting ​

Sort array elements alphabetically:

zig
try doc.sortArray("tags");

Reverse array order:

zig
try doc.reverseArray("tags");

Array Truncation ​

Shorten arrays by truncating, or dropping from start/end:

zig
try doc.truncate("arr", 2);     // keep only first 2 elements
try doc.dropFirst("arr", 1);    // remove first element
try doc.dropLast("arr", 2);     // remove last 2 elements

Array Cleanup ​

Remove null or duplicate values:

zig
try doc.compact("arr");  // remove all null values
try doc.unique("arr");   // remove duplicate string values

Array Boundaries ​

Access first and last elements:

zig
if (doc.first("arr")) |first| { /* ... */ }
if (doc.last("arr")) |last| { /* ... */ }

Array Predicate Checks ​

Check if all or any array elements satisfy a condition:

zig
fn isEven(v: *const zon.Value) bool {
    return @rem(v.asInt().?, 2) == 0;
}
const all_even = doc.every("nums", isEven);
const any_odd = doc.some("nums", isOdd);

Released under the MIT License.