Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I iterate over struct fields at compile time in Zig to generate a serializer?

I'm learning Zig and I'm trying to write a generic function that automatically serializes any struct into JSON. In languages like Rust or Go, there are libraries that can iterate over the fields of a struct at compile time. I was hoping to do something similar in Zig using @typeInfo.

Here is a simplified example of what I'm trying to do:

const std = @import("std");

const Example = struct {
    a: i32,
    b: []const u8,
    c: bool,
};

pub fn toJson(comptime T: type, value: T) []const u8 {
    // iterate over T's fields here
    // return a JSON string like {"a":1,"b":"hello","c":true}
}

I tried inspecting @typeInfo(T) and matching on TypeInfo.Struct to get the fields array, but I can't figure out how to loop over it in a way that works at compile time. If I write a normal for loop inside the function, Zig complains that it cannot evaluate it at compile time. If I try to use inline for, I get "expected comptime expression" errors. I've also looked at examples in the standard library but they use hard-coded field names.

What I've tried:

  • Using @typeInfo(T).Struct.fields inside an inline for loop. The compiler errors with "index is not comptime-known".
  • Attempting to build a []const u8 by concatenating the field names and values, but I run into lifetime and allocation issues since I can't allocate memory at comptime.
  • Searching the docs and examples for "reflection" or "struct fields" but most examples are about enums.

Is there a supported way in Zig (0.11 or 0.12) to iterate over the fields of a struct at compile time so I can generate code based on them? Or is this not possible and I need to manually write serialization functions for each struct?

Any pointers or examples would be greatly appreciated!

like image 216
Ronika Kashyap Avatar asked Dec 14 '25 03:12

Ronika Kashyap


1 Answers

In Zig 0.14.1, you need to use @TypeOf and @field:

const std = @import("std");

test "fields" {
    const U1s = packed struct {
        a: u1,
        b: u1,
        c: u1,
    };

    const x = U1s{ .a = 1, .b = 0, .c = 0 };
    inline for (std.meta.fields(@TypeOf(x))) |f| {
        std.debug.print(f.name ++ " {}\n", .{ @as(f.type, @field(x, f.name)) });
    }
}

This prints:

$ zig build test
test
└─ run test stderr
a 1
b 0
c 0

It should be very similar in 0.11 and 0.12.

like image 145
sigod Avatar answered Dec 16 '25 02:12

sigod



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!