{"id":49278736,"url":"https://github.com/leostera/zerde","last_synced_at":"2026-04-26T18:00:32.790Z","repository":{"id":352682083,"uuid":"1216182716","full_name":"leostera/zerde","owner":"leostera","description":"comptime-fused serialization library for zig","archived":false,"fork":false,"pushed_at":"2026-04-22T07:32:24.000Z","size":760,"stargazers_count":32,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-25T17:38:36.943Z","etag":null,"topics":["bson","cbor","deserialization","json","serde","serialization","toml","vibecoded","wasm","yaml","zig","zig-package"],"latest_commit_sha":null,"homepage":"","language":"Zig","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leostera.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"github":"leostera"}},"created_at":"2026-04-20T16:46:12.000Z","updated_at":"2026-04-25T12:32:11.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/leostera/zerde","commit_stats":null,"previous_names":["leostera/zerde"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/leostera/zerde","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leostera%2Fzerde","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leostera%2Fzerde/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leostera%2Fzerde/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leostera%2Fzerde/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leostera","download_url":"https://codeload.github.com/leostera/zerde/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leostera%2Fzerde/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32307015,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T17:23:19.671Z","status":"ssl_error","status_checked_at":"2026-04-26T17:23:19.195Z","response_time":129,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bson","cbor","deserialization","json","serde","serialization","toml","vibecoded","wasm","yaml","zig","zig-package"],"created_at":"2026-04-25T17:32:46.046Z","updated_at":"2026-04-26T18:00:32.781Z","avatar_url":"https://github.com/leostera.png","language":"Zig","funding_links":["https://github.com/sponsors/leostera"],"categories":[],"sub_categories":[],"readme":"# zerde\n\n`zerde` is a comptime-specialized serialization framework for Zig.\n\nPoint it at a Zig type and a format, and it generates a typed serializer or\ndeserializer for that exact combination.\n\nWhat you get:\n\n- one typed API across JSON, ZON, TOML, YAML, CBOR, BSON, MessagePack, and binary\n- fast read and write paths without a required runtime value tree\n- an optional `zerde.Value` tree for transcoding and schema-less tooling\n- per-type and per-call customization for field renames and wire-shape policy\n- owned, arena-backed, and aliased slice parse entrypoints\n- corpus-backed, property-tested, and fuzz-hardened format coverage\n- wasm/WASI pointer+length helpers for moving typed values across JS boundaries and parsing JSON, ZON, YAML, MessagePack, and other format payloads inside the module\n\nCurrent benchmark snapshot on the repo's mixed nested workload:\n\n- about `2.1x` faster than `std.json` on reads and `1.2x` faster on writes\n- about `1.3x` faster than `std.zon` on reads and `1.1x` faster on writes\n- about `1.7x` faster than `zig-toml` on reads and `1.1x` faster on writes\n- about `8x` faster than `zbor` on reads and `1.8x` faster on writes\n- about `2x` faster than `zig-yaml` on reads and `2.5x` faster on writes\n- about `9x` faster than `zig-bson` on reads and `3x` to `4x` faster on writes\n- about `4x` to `5x` faster than `bufzilla` on reads and `3x` to `4x` faster on writes\n\n```zig\nconst std = @import(\"std\");\nconst zerde = @import(\"zerde\");\n\nconst StrawHat = struct {\n    name: []const u8,\n    bounty: u32,\n    role: enum { captain, navigator, cook, shipwright },\n\n    pub const serde = .{\n        .rename_all = .snake_case,\n    };\n};\n\npub fn main() !void {\n    const allocator = std.heap.page_allocator;\n\n    const crew_mate = StrawHat{\n        .name = \"Franky\",\n        .bounty = 394_000_000,\n        .role = .shipwright,\n    };\n\n    var out: std.Io.Writer.Allocating = .init(allocator);\n    defer out.deinit();\n\n    try zerde.serialize(zerde.json, \u0026out.writer, crew_mate);\n\n    var decoded = try zerde.parseSliceOwned(zerde.json, StrawHat, allocator, out.written());\n    defer decoded.deinit();\n\n    std.debug.print(\"{s}\\n\", .{out.written()});\n}\n```\n\n## Formats\n\n| Format | Serialize | Reader deserialize | Slice deserialize | Aliased slice parse | Notes |\n| --- | --- | --- | --- | --- | --- |\n| Binary | yes | yes | yes | yes | Schema-driven compact binary format |\n| BSON | yes | yes | yes | yes | Typed BSON path |\n| MessagePack | yes | yes | yes | yes | Typed MessagePack path |\n| JSON | yes | yes | yes | yes | Fully typed fast path, benchmarked against `std.json` |\n| ZON | yes | yes | yes | no | Typed ZON path, benchmarked against `std.zon`; slice parse currently owns decoded strings |\n| TOML | yes | yes | yes | yes | Practical TOML subset centered on scalars, arrays, tables, and arrays-of-tables |\n| CBOR | yes | yes | yes | yes | Definite-length writer; read accepts definite and indefinite arrays/maps |\n| YAML | yes | yes | yes | yes | Practical block-YAML subset with block mappings, block sequences, and flow scalar arrays |\n\n## WebAssembly / WASI\n\n`zerde` is not limited to its compact binary transport in wasm.\n\nThe `zerde.wasm` helpers can:\n\n- serialize typed Zig values into wasm-friendly pointer+length buffers\n- parse JSON, ZON, YAML, MessagePack, and other supported payloads inside the module\n- reserialize those typed values back into JSON, binary, or another format before handing bytes back to JS\n\n```zig\nconst std = @import(\"std\");\nconst zerde = @import(\"zerde\");\n\nconst CrewManifest = struct {\n    captainName: []const u8,\n    bounty: u32,\n    shipwright: bool,\n\n    pub const serde = .{\n        .rename_all = .snake_case,\n    };\n};\n\npub fn normalizeJson(allocator: std.mem.Allocator, input: []const u8) !zerde.wasm.OwnedBuffer {\n    const manifest = try zerde.wasm.parseFormatWith(zerde.json, CrewManifest, allocator, zerde.wasm.sliceDescriptor(input), .{\n        .rename_all = .snake_case,\n    }, .{});\n    defer zerde.free(allocator, manifest);\n\n    return zerde.wasm.serializeFormatOwnedWith(zerde.json, allocator, manifest, .{\n        .rename_all = .snake_case,\n    }, .{});\n}\n```\n\nNative format examples and browser-oriented wasm examples live in [`examples/`](examples), and you can build them with `zig build examples`.\n\n## Install\n\nAdd `zerde` as a Zig dependency:\n\n```sh\nzig fetch --save git+https://github.com/leostera/zerde#0.1.0\n```\n\nThen import it from your `build.zig`:\n\n```zig\nconst zerde_dep = b.dependency(\"zerde\", .{\n    .target = target,\n    .optimize = optimize,\n});\n\nexe.root_module.addImport(\"zerde\", zerde_dep.module(\"zerde\"));\n```\n\nAnd from your Zig code:\n\n```zig\nconst zerde = @import(\"zerde\");\n```\n\nBenchmark history and per-format runs live in [`bench/`](bench).\n\n## CLI\n\n`zerde` also ships with a small transcoder for self-describing formats.\n\nBuild it with:\n\n```sh\nzig build transcode\n```\n\nThen use it like:\n\n```sh\n./zig-out/bin/zerde-transcode --from json --to yaml crew.json\n```\n\nIt currently supports `json`, `zon`, `toml`, `yaml`, `cbor`, `bson`, and `msgpack`.\n\n## Customization\n\n`zerde` accepts configuration at two levels:\n\n- call-site config passed to `serializeWith`, `deserializeWith`, `parseSliceWith`, or `parseSliceAliasedWith`\n- per-type config through `pub const serde = .{ ... }`\n\nSupported typed-layer options today:\n\n- `rename_all`\n- `omit_null_fields`\n- `deny_unknown_fields`\n- per-field `rename`\n\nExample:\n\n```zig\nconst std = @import(\"std\");\nconst zerde = @import(\"zerde\");\n\nconst User = struct {\n    firstName: []const u8,\n    createdAt: i64,\n    nickname: ?[]const u8,\n\n    pub const serde = .{\n        .rename_all = .snake_case,\n        .fields = .{\n            .createdAt = .{ .rename = \"created_at_unix\" },\n        },\n    };\n};\n\npub fn main() !void {\n    var out: std.Io.Writer.Allocating = .init(std.heap.page_allocator);\n    defer out.deinit();\n\n    try zerde.serializeWith(zerde.json, \u0026out.writer, User{\n        .firstName = \"Franky\",\n        .createdAt = 42,\n        .nickname = null,\n    }, .{\n        .omit_null_fields = true,\n    }, .{});\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleostera%2Fzerde","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleostera%2Fzerde","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleostera%2Fzerde/lists"}