### Install zimdjson Library Source: https://github.com/ezequielramis/zimdjson/blob/main/README.md Add the zimdjson library to your project using zig fetch. This command downloads the library and saves it for future builds. ```bash zig fetch --save git+https://github.com/ezequielramis/zimdjson#0.1.1 ``` -------------------------------- ### Parse JSON with Streaming Parser Source: https://github.com/ezequielramis/zimdjson/blob/main/README.md Use the streaming parser to handle large JSON documents efficiently with minimal memory. This example demonstrates parsing a file and extracting specific data. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.ondemand.StreamParser(.default).init; defer parser.deinit(allocator); const file = try std.fs.cwd().openFile("twitter.json", .{}); defer file.close(); const document = try parser.parseFromReader(allocator, file.reader().any()); const metadata_count = try document.at("search_metadata").at("count").asUnsigned(); std.debug.print("{} results.", .{metadata_count}); } ``` -------------------------------- ### Inspect unknown JSON value types with asAny Source: https://context7.com/ezequielramis/zimdjson/llms.txt When the JSON type is unknown, use `asAny()` to get an `AnyValue` tagged union. This allows you to inspect and handle different JSON types (null, boolean, number, string, object, array) dynamically. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); const inputs = [_][]const u8{ "42", "\"hello\"", "true", "null", "[1,2]" }; for (inputs) |json| { const document = try parser.parseFromSlice(allocator, json); const any = try document.asAny(); switch (any) { .number => |n| std.debug.print("number: {}\n", .{n}), .string => |s| std.debug.print("string: {s}\n", .{try s.get()}), .bool => |b| std.debug.print("bool: {}\n", .{b}), .null => std.debug.print("null\n", .{}), .array => std.debug.print("array\n", .{}), .object => std.debug.print("object\n", .{}), } } } ``` -------------------------------- ### Iterating Over Object Fields with Object.iterator Source: https://context7.com/ezequielramis/zimdjson/llms.txt Use `asObject().iterator()` to get an iterator for JSON object fields. Each field exposes a `.key` (RawString) and a `.value` (Value), allowing traversal of all key-value pairs in the object. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); const document = try parser.parseFromSlice(allocator, \{"alpha": 1, "beta": 2, "gamma": 3} ); var obj = try document.asObject(); var it = obj.iterator(); while (try it.next()) |field| { const key = try field.key.get(); // unescaped UTF-8 key const val = try field.value.asUnsigned(); std.debug.print("{s} = {} ", .{ key, val }); } // alpha = 1 // beta = 2 // gamma = 3 } ``` -------------------------------- ### Object.iterator Source: https://context7.com/ezequielramis/zimdjson/llms.txt Allows iteration over the fields of a JSON object. Call .asObject() to get an Object, then .iterator() to obtain an iterator that yields Fields. Each Field exposes a .key (RawString) and a .value (Value). ```APIDOC ## Object.iterator — iterate over object fields `asObject()` returns an `Object`. Call `.iterator()` to walk every `Field`, which exposes a `.key` (`RawString`) and a `.value` (`Value`). ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); const document = try parser.parseFromSlice(allocator, \{"alpha": 1, "beta": 2, "gamma": 3} ); var obj = try document.asObject(); var it = obj.iterator(); while (try it.next()) |field| { const key = try field.key.get(); // unescaped UTF-8 key const val = try field.value.asUnsigned(); std.debug.print("{s} = {}\n", .{ key, val }); } // alpha = 1 // beta = 2 // gamma = 3 } ``` ``` -------------------------------- ### Array.iterator Source: https://context7.com/ezequielramis/zimdjson/llms.txt Provides a forward-only iterator for JSON arrays. Call .asArray() to get an Array, then .iterator() to obtain the iterator. Each call to .next() returns an optional Value, with null indicating the end of the array. ```APIDOC ## Array.iterator — iterate over array elements `asArray()` returns an `Array`. Call `.iterator()` to get a forward-only `Array.Iterator`. Each call to `.next()` returns `?Value` — `null` signals end of array. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); const document = try parser.parseFromSlice(allocator, \[10, 20, 30, 40, 50] ); var arr = try document.asArray(); var it = arr.iterator(); var sum: u64 = 0; while (try it.next()) |value| { sum += try value.asUnsigned(); } std.debug.print("sum = {}\n", .{sum}); // sum = 150 } ``` ``` -------------------------------- ### Configure Union Representation for JSON Encoding Source: https://context7.com/ezequielramis/zimdjson/llms.txt Control how Zig tagged unions are encoded in JSON using different representation modes: externally_tagged, internally_tagged, adjacently_tagged, or untagged. This example demonstrates the 'internally_tagged' mode. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); const Parser = zimdjson.ondemand.FullParser(.default); // Internally tagged: {"type": "request", "id": "1", "method": "ping"} const Message = union(enum) { pub const schema: Parser.schema.Infer(@This()) = .{ .representation = .{ .internally_tagged = "type" }, }; request: struct { id: []const u8, method: []const u8 }, response: struct { id: []const u8, result: []const u8 }, }; pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = Parser.init; defer parser.deinit(allocator); const document = try parser.parseFromSlice(allocator, \{"type": "response", "id": "42", "result": "ok"} ); const msg = try document.as(Message, allocator, .{}); defer msg.deinit(); switch (msg.value) { .request => |r| std.debug.print("REQ id={s} method={s}\n", .{ r.id, r.method }), .response => |r| std.debug.print("RESP id={s} result={s}\n", .{ r.id, r.result }), } // RESP id=42 result=ok } ``` -------------------------------- ### Set Maximum Capacity and Depth for Parser Source: https://context7.com/ezequielramis/zimdjson/llms.txt Use setMaximumCapacity to reject documents exceeding a size limit (e.g., 1 MiB) and setMaximumDepth to limit nesting levels (e.g., 64). This guards against malformed or adversarial input. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); // Reject documents larger than 1 MiB. try parser.setMaximumCapacity(1024 * 1024); // Reject nesting deeper than 64 levels. parser.setMaximumDepth(64); const json = "{}"; const document = parser.parseFromSlice(allocator, json) catch |err| { std.debug.print("parse error: %\n", .{err}); return; }; _ = document; std.debug.print("parsed ok\n", .{} ); } ``` -------------------------------- ### Add zimdjson to Zig Project Source: https://context7.com/ezequielramis/zimdjson/llms.txt Fetch the zimdjson library using zig fetch and add it as a dependency in your build.zig file. ```sh zig fetch --save git+https://github.com/ezequielramis/zimdjson#0.1.1 ``` ```zig // build.zig const zimdjson = b.dependency("zimdjson", .{}); exe.root_module.addImport("zimdjson", zimdjson.module("zimdjson")); ``` -------------------------------- ### Arena-friendly deserialization with asLeaky Source: https://context7.com/ezequielramis/zimdjson/llms.txt Use `asLeaky(T, allocator, options)` for deserialization when using an `std.heap.ArenaAllocator`. This method skips individual allocation tracking, allowing the arena to manage bulk freeing, which is more efficient for temporary data structures. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); const Config = struct { host: []const u8, port: u16, debug: bool, }; pub fn main() !void { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); const allocator = arena.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); const document = try parser.parseFromSlice(allocator, \{"host": "localhost", "port": 8080, "debug": true} ); // No individual cleanup needed — arena handles everything. const config = try document.asLeaky(Config, allocator, .{}); std.debug.print("{s}:{} debug={}\n", .{ config.host, config.port, config.debug }); // localhost:8080 debug=true } ``` -------------------------------- ### Deserialize JSON using Reflection Source: https://github.com/ezequielramis/zimdjson/blob/main/README.md Leverage Zig's compile-time reflection for a Serde-like deserialization experience. Define a struct and parse JSON directly into it, reducing boilerplate code. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); const Film = struct { name: []const u8, year: u32, characters: []const []const u8, // we could also use std.ArrayListUnmanaged([]const u8) }; pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); const json = \{ \ "name": "Esperando la carroza", \ "year": 1985, \ "characters": [ \ "Mamá Cora", \ "Antonio", \ "Sergio", \ "Emilia", \ "Jorge" \ ] \} ; const document = try parser.parseFromSlice(allocator, json); const film = try document.as(Film, allocator, .{}); defer film.deinit(); try std.testing.expectEqualDeep( Film{ .name = "Esperando la carroza", .year = 1985, .characters = &.{ "Mamá Cora", "Antonio", "Sergio", "Emilia", "Jorge", }, }, film.value, ); } ``` -------------------------------- ### Zero-Copy String Access with RawString Source: https://context7.com/ezequielramis/zimdjson/llms.txt Utilize `asRawString()` for zero-copy access to JSON string data. Use `.getTemporal()` for a short-lived, unescaped slice or `.eqlRaw()` to compare against raw (unescaped) bytes without allocation. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); const document = try parser.parseFromSlice(allocator, \{"msg": "Hello\nWorld"} ); // getTemporal — valid only until the next string operation. const raw = document.at("msg").asRawString(); const temporal = try raw.getTemporal(); std.debug.print("temporal: {s}\n", .{temporal}); // temporal: Hello\nWorld (unescaped) // eqlRaw — compare against raw (unescaped) bytes without allocation. const same = try raw.eqlRaw("Hello\nWorld"); std.debug.print("eqlRaw: {}\n", .{same}); // eqlRaw: true } ``` -------------------------------- ### Add zimdjson to build.zig Source: https://github.com/ezequielramis/zimdjson/blob/main/README.md Include the zimdjson dependency in your build.zig file to make it available in your project. This sets up the build system to link against the library. ```zig const zimdjson = b.dependency("zimdjson", .{}); exe.root_module.addImport("zimdjson", zimdjson.module("zimdjson")); ``` -------------------------------- ### dom.FullParser Source: https://context7.com/ezequielramis/zimdjson/llms.txt The `zimdjson.dom.FullParser` builds a complete typed tree (tape) in memory. Every value is eagerly validated and accessible by type. This is useful when you need to traverse the document multiple times or require strict validation before any access. ```APIDOC ## dom.FullParser — DOM-style full validation `zimdjson.dom.FullParser` builds a complete typed tree (tape) in memory. Every value is eagerly validated and accessible by type. Useful when you need to traverse the document multiple times or require strict validation before any access. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.dom.FullParser(.default).init; defer parser.deinit(allocator); const document = try parser.parseFromSlice(allocator, \{"scores": [95, 87, 73, 100, 68]} ); var arr = try document.at("scores").asArray(); var it = arr.iterator(); var max: u64 = 0; while (try it.next()) |v| { const n = try v.asUnsigned(); if (n > max) max = n; } std.debug.print("max score: {}\n", .{max}); // max score: 100 } ``` ``` -------------------------------- ### Configure Struct Schema for Field Renaming and Unknown Fields Source: https://context7.com/ezequielramis/zimdjson/llms.txt Use embedded schema options to rename JSON keys to PascalCase, override specific field names (e.g., 'ids' to 'IDs'), and specify how to handle unknown fields during parsing. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); // Parser type alias used to refer to schema helpers. const Parser = zimdjson.ondemand.FullParser(.default); const Image = struct { // Embedded schema: rename all keys to PascalCase, override "ids" → "IDs". pub const schema: Parser.schema.Infer(@This()) = .{ .rename_all = .PascalCase, .fields = .{ .ids = .{ .rename = "IDs" } }, .on_unknown_field = .ignore, }; width: u16, height: u16, title: []const u8, ids: []const u16, }; pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = Parser.init; defer parser.deinit(allocator); const document = try parser.parseFromSlice(allocator, \{"Width": 1920, "Height": 1080, "Title": "Sunset", "IDs": [1, 2, 3]} ); const img = try document.as(Image, allocator, .{}); defer img.deinit(); std.debug.print("{}x{} '{}' ids={}\n", .{ img.value.width, img.value.height, img.value.title, img.value.ids.len, }); // 1920x1080 'Sunset' ids=3 } ``` -------------------------------- ### ondemand.FullParser - parse a complete document from a slice Source: https://context7.com/ezequielramis/zimdjson/llms.txt The FullParser parses the entire JSON document into memory in one pass, allowing for lazy navigation of the data. It is suitable for documents up to 4 GiB and should be reused for optimal performance. ```APIDOC ## ondemand.FullParser - parse a complete document from a slice ### Description Parses a complete JSON document from a slice of bytes, building an in-memory index for lazy navigation. Suitable for documents up to 4 GiB. The parser should be reused across multiple parsing operations for best performance. ### Method `FullParser(options).init` followed by `parser.parseFromSlice(allocator, json_slice)` ### Parameters #### `FullParser` Options - `options`: Configuration for the parser. Use `.default` for default settings. #### `parseFromSlice` Parameters - `allocator`: An allocator to use for memory management. - `json_slice`: A slice of bytes containing the JSON data. ### Request Example ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); var gpa = std.heap.GeneralPurposeAllocator(.{}).init; defer _ = gpa.deinit(); const allocator = gpa.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); const json = \ \{ \ \"Image\": { \ \ \"Width\": 800, \ \ \"Height\": 600, \ \ \"Title\": \"View from 15th Floor\", \ \ \"Animated\": false, \ \ \"IDs\": [116, 943, 234, 38793] \ \ } \ \} ; const document = try parser.parseFromSlice(allocator, json); const title = try document.at("Image").at("Title").asString(); std.debug.print("Title: {s}\\n", .{title}); const third_id = try document.at("Image").at("IDs").atIndex(2).asUnsigned(); std.debug.print("3rd ID: {d}\\n", .{third_id}); const animated = try document.at("Image").at("Animated").asBool(); std.debug.print("Animated: {b}\\n", .{animated}); ``` ### Response - `document`: A lazy `Value` representing the parsed JSON document. - Methods like `.asString()`, `.asUnsigned()`, `.asBool()` can be called on navigated `Value`s to retrieve data. ### Success Response Example ``` Title: View from 15th Floor 3rd ID: 234 Animated: false ``` ``` -------------------------------- ### Ordered Field Lookup with Document.atOrdered Source: https://context7.com/ezequielramis/zimdjson/llms.txt Use `atOrdered(key)` for faster lookups when the JSON field order is known and controlled. This method scans forward only and does not backtrack, making it more efficient if keys are accessed in their appearance order. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); // Keys MUST be accessed in the order they appear in the JSON. const document = try parser.parseFromSlice(allocator, \{ "x": 1.0, "y": 2.5, "z": -3.0 } ); const x = try document.atOrdered("x").asDouble(); const y = try document.atOrdered("y").asDouble(); const z = try document.atOrdered("z").asDouble(); std.debug.print("x={d} y={d} z={d} ", .{ x, y, z }); // x=1.0 y=2.5 z=-3.0 } ``` -------------------------------- ### Unordered Field Lookup with Document.at Source: https://context7.com/ezequielramis/zimdjson/llms.txt Use `at(key)` for flexible, chainable lookups in JSON objects where field order is not guaranteed. It returns a lazy `Value` that defers error handling until a terminal cast is called. Chaining multiple `.at()` calls allows drilling into nested objects. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); const document = try parser.parseFromSlice(allocator, \{ "a": { "b": { "c": 42 } } } ); // Any lookup order works — field order in JSON is irrelevant. const value = try document.at("a").at("b").at("c").asUnsigned(); std.debug.assert(value == 42); // error.MissingField is returned (lazily) when a key is absent. const missing = document.at("a").at("x").asUnsigned(); std.debug.print("missing: {} ", .{missing}); // error.MissingField } ``` -------------------------------- ### Parse JSON Document from Slice with FullParser Source: https://context7.com/ezequielramis/zimdjson/llms.txt Use FullParser to parse a complete JSON document from a string slice. The parser owns the memory and should be reused. Access fields using chained .at() calls and cast values with .asString(), .asUnsigned(), or .asBool(). ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; defer _ = gpa.deinit(); const allocator = gpa.allocator(); // Create a reusable parser (default options, unaligned input). var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); const json = \{ \ "Image": { \ "Width": 800, \ "Height": 600, \ "Title": "View from 15th Floor", \ "Animated": false, \ "IDs": [116, 943, 234, 38793] \ } \} ; const document = try parser.parseFromSlice(allocator, json); // Chained field access — returns a lazy Value, error deferred until cast. const title = try document.at("Image").at("Title").asString(); std.debug.print("Title: {s}\n", .{title}); // Title: View from 15th Floor const third_id = try document.at("Image").at("IDs").atIndex(2).asUnsigned(); std.debug.print("3rd ID: {}\n", .{third_id}); // 3rd ID: 234 const animated = try document.at("Image").at("Animated").asBool(); std.debug.print("Animated: {}\n", .{animated}); // Animated: false } ``` -------------------------------- ### Parser.setMaximumCapacity / setMaximumDepth Source: https://context7.com/ezequielramis/zimdjson/llms.txt These methods allow you to set safety limits for the JSON parser, preventing it from accepting documents larger than a specified capacity or nested deeper than a given level. This is crucial for guarding against malformed or adversarial input. ```APIDOC ## Parser.setMaximumCapacity / setMaximumDepth — safety limits Prevent the parser from accepting documents larger than an expected bound or nested deeper than a given level, guarding against malformed or adversarial input. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); // Reject documents larger than 1 MiB. try parser.setMaximumCapacity(1024 * 1024); // Reject nesting deeper than 64 levels. parser.setMaximumDepth(64); const json = "{}"; const document = parser.parseFromSlice(allocator, json) catch |err| { std.debug.print("parse error: {}\n", .{!err}); return; }; _ = document; std.debug.print("parsed ok\n", .{}); } ``` ``` -------------------------------- ### Array Element Access with Document.atIndex Source: https://context7.com/ezequielramis/zimdjson/llms.txt Access elements in a JSON array by their zero-based index using `atIndex(n)`. This operation is O(n) as it scans from the beginning of the array. An `error.IndexOutOfBounds` is returned lazily if the index does not exist. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); const document = try parser.parseFromSlice(allocator, \[ ["a", "b"], ["c", "d"], ["e", "f"] ] ); // Nested array access via chained atIndex. const val = try document.atIndex(1).atIndex(0).asString(); std.debug.print("{s} ", .{val}); // c } ``` -------------------------------- ### Document.at / Value.at Source: https://context7.com/ezequielramis/zimdjson/llms.txt Performs an unordered field lookup by name. Chaining multiple .at() calls allows drilling through nested objects. Returns a lazy Value that carries errors until a terminal cast. ```APIDOC ## Document.at / Value.at — unordered field lookup (chainable) `at(key)` looks up a field by name without requiring any particular key order. It returns a lazy `Value` that carries any error until a terminal cast (`.asString()`, `.asUnsigned()`, etc.) is called. Multiple `.at()` calls may be chained to drill through nested objects. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); const document = try parser.parseFromSlice(allocator, \{ "a": { "b": { "c": 42 } } } ); // Any lookup order works — field order in JSON is irrelevant. const value = try document.at("a").at("b").at("c").asUnsigned(); std.debug.assert(value == 42); // error.MissingField is returned (lazily) when a key is absent. const missing = document.at("a").at("x").asUnsigned(); std.debug.print("missing: {}\n", .{missing}); // error.MissingField } ``` ``` -------------------------------- ### DOM-style FullParser for Strict Validation Source: https://context7.com/ezequielramis/zimdjson/llms.txt Utilize zimdjson.dom.FullParser to build a complete, typed in-memory tree. This parser eagerly validates every value and is useful for multiple traversals or strict validation before data access. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.dom.FullParser(.default).init; defer parser.deinit(allocator); const document = try parser.parseFromSlice(allocator, \{"scores": [95, 87, 73, 100, 68]} ); var arr = try document.at("scores").asArray(); var it = arr.iterator(); var max: u64 = 0; while (try it.next()) |v| { const n = try v.asUnsigned(); if (n > max) max = n; } std.debug.print("max score: %\n", .{max}); // max score: 100 } ``` -------------------------------- ### Deserialize JSON into Zig types using reflection Source: https://context7.com/ezequielramis/zimdjson/llms.txt Utilize `as(T, allocator, options)` for reflection-based deserialization directly into Zig types like structs, enums, unions, and slices. The returned `Parsed(T)` manages memory, requiring a call to `.deinit()`. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); const Film = struct { name: []const u8, year: u32, characters: []const []const u8, }; pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); const json = \{ \ "name": "Esperando la carroza", \ "year": 1985, \ "characters": ["Mamá Cora", "Antonio", "Sergio", "Emilia", "Jorge"] \} ; const document = try parser.parseFromSlice(allocator, json); // Deserialize the whole document into Film; memory managed by returned Parsed. const film = try document.as(Film, allocator, .{}); defer film.deinit(); std.debug.print("{s} ({}) — {} characters\n", .{ film.value.name, film.value.year, film.value.characters.len, }); // Esperando la carroza (1985) — 5 characters } ``` -------------------------------- ### Cast JSON values to specific Zig types Source: https://context7.com/ezequielramis/zimdjson/llms.txt Use typed accessor methods like asString, asUnsigned, asDouble, asBool, and isNull to safely retrieve values from a JSON document. Errors are returned as Zig error unions, preventing panics. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); const document = try parser.parseFromSlice(allocator, \{ \ "name": "Alice", \ "age": 30, \ "balance": -4.5, \ "active": true, \ "nickname": null \} ); const name = try document.at("name").asString(); // []const u8 const age = try document.at("age").asUnsigned(); // u64 const balance = try document.at("balance").asDouble(); // f64 const active = try document.at("active").asBool(); // bool const is_null = try document.at("nickname").isNull(); // bool std.debug.print("name={s} age={} balance={d} active={} null={}\n", .{ name, age, balance, active, is_null }); // name=Alice age=30 balance=-4.5 active=true null=true } ``` -------------------------------- ### Iterating Over Array Elements with Array.iterator Source: https://context7.com/ezequielramis/zimdjson/llms.txt Obtain an `Array.Iterator` from a JSON array using `.asArray().iterator()`. Iterate through elements using `.next()`, which returns `?Value`. A `null` return signals the end of the array. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); const document = try parser.parseFromSlice(allocator, \[10, 20, 30, 40, 50] ); var arr = try document.asArray(); var it = arr.iterator(); var sum: u64 = 0; while (try it.next()) |value| { sum += try value.asUnsigned(); } std.debug.print("sum = {} ", .{sum}); // sum = 150 } ``` -------------------------------- ### Parse Large JSON Document with StreamParser Source: https://context7.com/ezequielramis/zimdjson/llms.txt Use StreamParser to process arbitrarily large JSON documents from a reader with constant memory usage. Configure chunk size via StreamOptions.chunk_length. Access fields similarly to FullParser. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; defer _ = gpa.deinit(); const allocator = gpa.allocator(); // StreamParser with a custom 128 KiB chunk size. const Options: zimdjson.ondemand.StreamOptions = .{ .chunk_length = 128 * 1024 }; var parser = zimdjson.ondemand.StreamParser(Options).init; defer parser.deinit(allocator); // Open a multi-gigabyte file — memory stays O(1). const file = try std.fs.cwd().openFile("twitter.json", .{}); defer file.close(); const document = try parser.parseFromReader(allocator, file.reader().any()); // Drill into nested fields exactly as with FullParser. const count = try document.at("search_metadata").at("count").asUnsigned(); std.debug.print("{} results\n", .{count}); // 100 results } ``` -------------------------------- ### Document.atOrdered / Value.atOrdered Source: https://context7.com/ezequielramis/zimdjson/llms.txt A faster variant of .at() that performs an ordered field lookup. It scans forward only and does not backtrack. Use when the JSON field order is known or controlled. ```APIDOC ## Document.atOrdered / Value.atOrdered — ordered field lookup `atOrdered(key)` is the faster variant of `at`. It scans forward only — it will not backtrack to find a key that appears earlier in the object than the last key accessed. Use it when you know (or control) the JSON field order. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); // Keys MUST be accessed in the order they appear in the JSON. const document = try parser.parseFromSlice(allocator, \{ "x": 1.0, "y": 2.5, "z": -3.0 } ); const x = try document.atOrdered("x").asDouble(); const y = try document.atOrdered("y").asDouble(); const z = try document.atOrdered("z").asDouble(); std.debug.print("x={d} y={d} z={d}\n", .{ x, y, z }); // x=1.0 y=2.5 z=-3.0 } ``` ``` -------------------------------- ### Document.atIndex / Array.at Source: https://context7.com/ezequielramis/zimdjson/llms.txt Accesses an element in a JSON array by its zero-based index. This operation is O(n) as it scans from the beginning of the array. Returns error.IndexOutOfBounds if the index is invalid. ```APIDOC ## Document.atIndex / Array.at — index into JSON arrays `atIndex(n)` on a document or value, and `at(n)` on an `Array`, return the element at zero-based index `n`. The operation is O(n) because arrays are scanned from the beginning. Returns `error.IndexOutOfBounds` (deferred) when the index does not exist. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); const document = try parser.parseFromSlice(allocator, \[ ["a", "b"], ["c", "d"], ["e", "f"] ] ); // Nested array access via chained atIndex. const val = try document.atIndex(1).atIndex(0).asString(); std.debug.print("{s}\n", .{val}); // c } ``` ``` -------------------------------- ### Number type Source: https://context7.com/ezequielramis/zimdjson/llms.txt `zimdjson.Number` is the result of `.asNumber()`. It distinguishes unsigned integers, signed integers, and doubles based on the literal format in the JSON source. Use `.lossyCast(T)` or `.cast(T)` to convert to a specific Zig numeric type. ```APIDOC ## Number type — tagged union for JSON numbers `zimdjson.Number` is the result of `.asNumber()`. It distinguishes unsigned integers, signed integers, and doubles based on the literal format in the JSON source. Use `.lossyCast(T)` or `.cast(T)` to convert to a specific Zig numeric type. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); const inputs = [_][]const u8{ "42", "-7", "3.14" }; for (inputs) |json| { const document = try parser.parseFromSlice(allocator, json); const n = try document.asNumber(); switch (n) { .unsigned => |v| std.debug.print("unsigned: {}\n", .{v}), .signed => |v| std.debug.print("signed: {}\n", .{v}), .double => |v| std.debug.print("double: {d}\n", .{v}), } // Cast to f32 safely: const f: f32 = n.lossyCast(f32); std.debug.print(" as f32: {d}\n", .{f}); } } ``` ``` -------------------------------- ### ondemand.StreamParser - parse an arbitrarily large document from a reader Source: https://context7.com/ezequielramis/zimdjson/llms.txt The StreamParser processes JSON documents in configurable chunks, maintaining constant memory usage regardless of document size. It is ideal for arbitrarily large files and integrates with any `std.io.AnyReader`. ```APIDOC ## ondemand.StreamParser - parse an arbitrarily large document from a reader ### Description Processes arbitrarily large JSON documents by reading them in configurable chunks, ensuring constant memory usage. This parser can be used with any `std.io.AnyReader`. ### Method `StreamParser(options).init` followed by `parser.parseFromReader(allocator, reader)` ### Parameters #### `StreamParser` Options - `options`: Configuration for the stream parser. `StreamOptions.chunk_length` can be set to tune the chunk size (default is 64 KiB). #### `parseFromReader` Parameters - `allocator`: An allocator to use for memory management. - `reader`: An instance of `std.io.AnyReader` to read the JSON data from. ### Request Example ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); var gpa = std.heap.GeneralPurposeAllocator(.{}).init; defer _ = gpa.deinit(); const allocator = gpa.allocator(); const Options: zimdjson.ondemand.StreamOptions = .{ .chunk_length = 128 * 1024 }; var parser = zimdjson.ondemand.StreamParser(Options).init; defer parser.deinit(allocator); const file = try std.fs.cwd().openFile("twitter.json", .{}); defer file.close(); const document = try parser.parseFromReader(allocator, file.reader().any()); const count = try document.at("search_metadata").at("count").asUnsigned(); std.debug.print("{d} results\\n", .{count}); ``` ### Response - `document`: A lazy `Value` representing the parsed JSON document. - Navigation and data retrieval methods are identical to `FullParser`. ### Success Response Example ``` 100 results ``` ``` -------------------------------- ### Handling JSON Numbers with zimdjson.Number Source: https://context7.com/ezequielramis/zimdjson/llms.txt The zimdjson.Number type distinguishes between unsigned integers, signed integers, and doubles based on the JSON literal format. Use .lossyCast(T) or .cast(T) to convert to specific Zig numeric types. ```zig const std = @import("std"); const zimdjson = @import("zimdjson"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}).init; const allocator = gpa.allocator(); var parser = zimdjson.ondemand.FullParser(.default).init; defer parser.deinit(allocator); const inputs = [_][]const u8{ "42", "-7", "3.14" }; for (inputs) |json| { const document = try parser.parseFromSlice(allocator, json); const n = try document.asNumber(); switch (n) { .unsigned => |v| std.debug.print("unsigned: %\n", .{v}), .signed => |v| std.debug.print("signed: %\n", .{v}), .double => |v| std.debug.print("double: {d}\n", .{v}), } // Cast to f32 safely: const f: f32 = n.lossyCast(f32); std.debug.print(" as f32: {d}\n", .{f}); } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.