I can’t find a better title for this. What I’m asking for example:

const arr: std.ArrayList(usize) = .empty;

Is there a method that let me check if arr is an instance of the generic ArrayList struct. My main use for this is to make my own json parse that support zig first party structs without a struct wrapper like how std.json does.

I making a game, and de/serializing ArrayList and AutoHashMap for every struct with jsonParse and jsonSerialize is driving me crazy.

If it’s not possible, is there a better method without a wrapper type for ArrayList or HashMap?

lufe July 11, 2026, 6:01pm 2

const std = @import("std");

fn isArrayList(t: type) bool {
    const name = "array_list.Aligned";
    return std.mem.eql(u8, name, @typeName(t)[0..name.len]);
}

pub fn main() !void {
    const l: std.ArrayList(u32) = .empty;
    if (isArrayList(@TypeOf(l))) {
        std.debug.print("l is array list.\n", .{});
    } else {
        std.debug.print("l is not array list.\n", .{});
    }

    const s: struct {} = undefined;
    if (isArrayList(@TypeOf(s))) {
        std.debug.print("s is array list.\n", .{});
    } else {
        std.debug.print("s is not array list.\n", .{});
    }
}

:grimacing:

I was about to edit the post to include that I thought of this method. I didn’t like it because I thought it was cursed :distorted_face:

I guess there is no other way…

What are you trying to do with this? This seems hacky so I’m guessing there’s a better way to do what you actually want to be accomplished.

How about this - Check if the provided struct has declaration (or field, I Always confuse these 2) named “items”
Take the type of that declaration, if it’s a slice of T then take T.
Return true if the type provided to the function == std.ArrayList(T).
If you need help I can try to write it. I think it should work.

I didn’t write the parse yet, this is a small snippet from the std.json:

      switch (@typeInfo(T)) {
        .bool => ...,
        .float, .comptime_float => ...,
        .int, .comptime_int => ...,
        .optional => |optionalInfo| ...,
        .@"enum" => ...,
        .@"union" => |unionInfo| ...,
        .@"struct" => |structInfo| ...,
        .array => |arrayInfo| ...,
        .vector => |vector_info| ...,
        .pointer => |ptrInfo| ...,
        else => @compileError("Unable to parse into type '" ++ @typeName(T) ++ "'"),
    }

What I basically want in the @"struct" branch is to check if the struct is an ArrayList or a HashMap and have a custom parsing for them.

A small function like this might work:

pub fn isArrayList(value: anytype) ?type {
    if (!@hasField(@TypeOf(value), "items")) return null;
    const info = @typeInfo(@TypeOf(value.items));
    if (info != .pointer) return null;
    return info.pointer.child;
}

lufe July 11, 2026, 6:56pm 8

Essentially this function checks for a string as well. Not a game dev, but a slice of “items” sounds to me like it could appear in a game code quite regularly. So maybe the check for this could give a false positive by accident more likely?

lufe July 11, 2026, 6:57pm 9

Ah, I missed the

part, you should integrate that part as well, I think.

castholm July 11, 2026, 7:00pm 10

You want to directly compare to T == std.ArrayList(...) after you find the element type, like so:

const std = @import("std");

fn isArrayList(T: type) bool {
    if (!@hasField(T, "items")) return false;
    return switch (@typeInfo(@FieldType(T, "items"))) {
        .pointer => |info| T == std.ArrayList(info.child),
        else => false,
    };
}

test isArrayList {
    const A = std.ArrayList(u8);
    const B = std.ArrayList(i32);
    const C = struct { items: []const i32 };
    const D = struct {};

    try std.testing.expect(isArrayList(A));
    try std.testing.expect(isArrayList(B));
    try std.testing.expect(!isArrayList(C));
    try std.testing.expect(!isArrayList(D));
}

You should not use @typeName to compare types. The @typeName string is not stable and may change between compilation runs or Zig releases, and is also possible to spoof. The above check will always be correct.

Karim.MK July 11, 2026, 7:08pm 11

Clever!
I do wander tho, if I were to make a patch to std.json rather than create my own json parser would it be accepted. Because, I think this should be supported for first-party collections imo.

castholm July 11, 2026, 7:22pm 12

I suspect that such a PR would be rejected, because different data structures are useful for different situations and std APIs favoring one or a few over all others will have the side effect of leading people to using the wrong tool for the job out of laziness/convenience.

In this case the more favored thing to do would probably be to either parse/serialize the array list as is, with an items field (i.e. {"foo":{"items":[1,2,3]}} in JSON), or use one of the dynamic JSON APIs to first parse into a regular plain slice and then instantiate an array list using .fromOwnedSlice or .initBuffer.

Edit: I quickly changed my mind, I actually think parsing and serializing array lists directly is bad because with the separate items and capacity you run a great risk of inadvertently violating important invariants.