JSON to Zig struct
Paste one JSON document or several samples of the same payload. zigshape writes Zig structs that std.json.parseFromSlice reads without changes, and explains every type it picked.
API responseSmallest int widths from observed range; auto enum suggestion; missing/null become optional.
{
"id": 42,
"name": "Alice",
"email": "alice@example.com",
"roles": ["admin", "user"],
"profile": { "createdAt": "2026-01-01T10:00:00Z", "active": true }
}User.zig pub const User = struct {
id: u8,
name: []const u8,
email: []const u8,
roles: []const []const u8,
profile: Profile,
};
pub const Profile = struct {
createdAt: []const u8,
active: bool,
};
Diagnostics
2 warningsField decisions
Why each field got its type. Click a row to see it in the input; edit to override.
struct User $ 5 fields
struct Profile $.profile 2 fields
What zigshape decides for std.json
- Field names stay exactly as the JSON keys (
@"first-name"where needed), because std.json matches names literally and has no rename. - A key missing or
nullin any sample becomes?T = null. - Integers get the smallest width that fits every observed value; the Strict preset switches to
u64. - Objects with dynamic keys become
std.json.ArrayHashMap(V), the map type std.json can parse. - Fields with no usable signal fall back to
std.json.Value, with a warning that says why.
Questions
- How do I parse JSON into the generated struct?
- Call
std.json.parseFromSlice(User, allocator, input, .{})anddeinit()the result. The More menu copies a readyparseUserhelper and a test that parses your sample. - Why are the field names camelCase instead of snake_case?
- std.json maps JSON keys to field names one to one, so renaming a field breaks parsing. Switch the target to serde.zig to get snake_case fields with
rename_all. - Can I generate one struct from several JSON responses?
- Yes. Add every response as a sample. Keys that are missing from some samples become optional, and the field table shows how often each key appeared.
- Does my JSON leave the browser?
- No. Parsing, inference and zig fmt all run locally; share links keep the data in the URL hash, which browsers never send to a server.