3

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!

1
  • Why not 0.14? Why 0.11 or 0.12? Commented Aug 13 at 10:52

1 Answer 1

4

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.