🚀 jsmn_zig - JSON Tokenizer for Zig
A lean, mean, JSON-parsing machine that doesn’t believe in bloat.
What’s This All About?
Ever felt like JSON parsers are over-engineered kitchen sinks that do everything except make coffee? Meet jsmn_zig
- a spiritual port of the legendary JSMN to Zig, with some Zig-ish improvements.
We don’t parse JSON into fancy ASTs. We give you tokens. You decide what to do with them. It’s like IKEA furniture for JSON - we give you the pieces, you build the masterpiece.
Features That Don’t Waste Your Time
- 🎯 Zero-copy tokenization - Because copying data is so 1990s
- 📦 Compact tokens - 32 bits per token (when we can get away with it)
- 🌊 Streaming support - Parse chunks like a boss
- **🧠 Hybri…
🚀 jsmn_zig - JSON Tokenizer for Zig
A lean, mean, JSON-parsing machine that doesn’t believe in bloat.
What’s This All About?
Ever felt like JSON parsers are over-engineered kitchen sinks that do everything except make coffee? Meet jsmn_zig
- a spiritual port of the legendary JSMN to Zig, with some Zig-ish improvements.
We don’t parse JSON into fancy ASTs. We give you tokens. You decide what to do with them. It’s like IKEA furniture for JSON - we give you the pieces, you build the masterpiece.
Features That Don’t Waste Your Time
- 🎯 Zero-copy tokenization - Because copying data is so 1990s
- 📦 Compact tokens - 32 bits per token (when we can get away with it)
- 🌊 Streaming support - Parse chunks like a boss
- 🧠 Hybrid memory - Stack for small stuff, heap when you’re feeling fancy
- ⚡ SIMD-ready - Because we like going fast
- 📱 Embedded-friendly - Works where other parsers would cry
Quick Start (For the Impatient)
const jsmn = @import("jsmn_zig.zig");
// The lazy way (we won't judge)
const Parser = jsmn.Jsmn(jsmn.jsmn_default_config());
var tokens: [32]Parser.Token = undefined;
var parents: [32]Parser.IndexT = undefined;
const json = "{\"answer\": 42}";
const count = try Parser.parseTokens(&tokens, &parents, json);
// Look ma, no allocations!
std.debug.print("Found {} tokens\n", .{count});
The Fancy Way
const cfg = jsmn.jsmn_default_config();
cfg.compact_tokens = true; // Save those precious bytes
cfg.max_depth = 256; // Don't trust deep JSON? We get it.
const Parser = jsmn.Jsmn(cfg);
// Let the parser handle memory like a responsible adult
const result = try Parser.parseHybrid(allocator, giant_json_string);
defer result.deinit(allocator);
// Do something cool with your tokens
for (result.heap_slice) |token| {
const slice = giant_json_string[token.getStart()..token.getEnd()];
std.debug.print("Token: {s}\n", .{slice});
}
Configuration Options (Because Choice is Good)
const config = jsmn.jsmn_default_config();
config.compact_tokens = true; // Pack tokens into 32 bits
config.max_depth = 1024; // Prevent stack overflow (the bad kind)
config.tiny_mode = false; // Strip helpers for maximum minimalism
config.enable_helpers = true; // Keep the training wheels on
config.use_simd = null; // Let us guess what's best for your CPU
API Highlights (The Good Parts)
Basic Tokenization
// The workhorse
try Parser.parseTokens(tokens, parents, input);
// For when you're dealing with streams
var state = Parser.ParserState{};
try Parser.parseChunk(&state, tokens, parents, chunk1, false);
try Parser.parseChunk(&state, tokens, parents, chunk2, true);
Memory-Smart Parsing
// Stack-only (for the purists)
const direct = try Parser.parseDirect(64, small_json);
// Hybrid approach (for the pragmatic)
const hybrid = try Parser.parseHybrid(allocator, unpredictable_json);
Helpers (Because Sometimes You’re Lazy)
// Find values without the hassle
if (Parser.findObjectValue(tokens, count, json, "username")) |value_idx| {
const username = Parser.tokenText(tokens[value_idx], json);
}
// Iterate arrays like it's nobody's business
const items = Parser.getArrayItems(tokens, array_index);
Performance Notes (The Boring But Important Part)
- Compact tokens save ~12 bytes per token vs standard tokens
- Stack parsing avoids heap allocations for JSON < ~512 tokens
- SIMD parsing kicks in automatically on supported architectures
- Zero-copy means we’re basically cheating at performance
When to Use This (And When Not To)
✅ Perfect For:
- Embedded systems (where every byte counts)
- High-performance parsing (when you need speed)
- Streaming JSON (network, files, carrier pigeons)
- Educational purposes (learn how parsing actually works)
❌ Maybe Not For:
- JSON schema validation (we just tokenize, bro)
- DOM-style manipulation (build your own tree)
- People who want magic (we’re wizards, not magicians)
Contributing
Found a bug? Have an improvement? We love those!
- Fork it
- Fix it
- Test it (zig test jsmn_zig.zig)
- PR it
License
MIT - because sharing is caring, and lawyers are expensive.
Built with ❤️ and enough coffee to power a small European country.