Skip to content

muhammad-fiaz/zon.zig

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

logo

zon.zig

Documentation Zig Version GitHub stars GitHub issues GitHub pull requests GitHub last commit License CI Supported Platforms Release Latest Release Sponsor GitHub Sponsors Downloads Repo Visitors

A simple, direct Zig library for reading and writing ZON (Zig Object Notation) files.

📚 Documentation | API Reference | Quick Start | Allocators | Contributing


A document-based ZON (Zig Object Notation) library for Zig, designed for configuration file editing, dynamic access, and data manipulation. Unlike std.zon which parses ZON into typed structures, zon.zig maintains an in-memory document tree that you can query, modify, and serialize.

⭐️ If you find zon.zig useful, please give it a star! ⭐️


🔄 zon.zig vs std.zon (click to expand)
Feature zon.zig std.zon
Approach Document-based (DOM tree) Type-based (deserialization)
Best For Config editing, dynamic access Type-safe parsing into structs
Modification Full read/write/edit/merge Read-only (serialize separately)
Path Access Dot notation ("db.host") Direct field access
Dependencies Custom parser (No Ast dependency) Uses std.zig.Ast, Zoir
Stability Independent of compiler internals Tied to Zig compiler API
Special Values NaN, Inf, -Inf support Limited in some Zig versions

Use zon.zig when:

  • You need to edit and save configuration files programmatically.
  • The structure isn't known at compile time or varies.
  • You want advanced features like Deep Merge, Find & Replace, and Deep Equality.
  • You need a lightweight parser that doesn't pull in std.zig.Ast.

Use std.zon when:

  • You know the structure at compile time and want static type safety.
  • You're using @import for compile-time ZON values.

✨ Features of zon.zig (click to expand)
Feature Description
📖 Simple API Clean open, get, set, delete, save interface
🔗 Path-Based Access Use dot notation like "dependencies.foo.path"
🏗️ Auto-Create Nested Objects Missing intermediate paths are created automatically
🔒 Type-Safe Getters getString, getBool, getInt, getFloat, getNumber
🛡️ No Panics Missing paths return null, type mismatches return null
🔧 Custom Parser Does NOT depend on std.zig.Ast or compiler internals
📝 Pretty Print Formatted output with configurable indentation
🔍 Find & Replace Search and replace values throughout the document
📋 Array Operations Get length, elements, append to arrays
🔄 Merge & Clone Shallow & Deep Merge, Combine documents, Deep copy
📏 Multi-line Strings Full support for multi-line backslash syntax (\\)
♾️ Special Floats Support for inf, -inf, and nan values
⚖️ Deep Equality Deeply compare two ZON documents or values
🖥️ Cross-Platform Windows, Linux, macOS (32-bit and 64-bit)
📦 Zero Dependencies Built entirely on the Zig standard library
High Performance Efficient parsing and serialization
🔄 Update Checker Optional automatic update checking (can be disabled)
📁 File Operations Delete, copy, rename, check existence
🧠 Memory Flexibility Full support for GPA, Arena, and custom allocators
🌐 JSON Interop Import from and Export to standard JSON
📏 Object Iterators Programmatic iteration over key-value pairs and arrays
🏗️ Flatten & Expand Convert nested ZON to flat dot-notation maps
🛡️ Integrity Suite Stable Hashing (Order-independent) & Checksums
📏 Size Metrics Calculate byte size and compact size of documents
🔍 Recursive Search Find keys anywhere (find, findAll)
🔁 Aliases Use preferred naming (e.g., init/new, len/size)
📂 File Key Utils Move/Copy keys directly in files without full parsing
📊 Diagnostic Errors High-quality syntax error reporting with line/column

📌 Prerequisites & Supported Platforms (click to expand)

Prerequisites

Requirement Version Notes
Zig 0.15.0+ Download from ziglang.org
Operating System Windows 10+, Linux, macOS Cross-platform support

Supported Platforms

Platform 32-bit 64-bit ARM Status
Windows ✅ x86 ✅ x86_64 - Full support
Linux ✅ x86 ✅ x86_64 ✅ aarch64 Full support
macOS ✅ x86 ✅ x86_64 ✅ aarch64 (Apple Silicon) Full support
Freestanding ✅ x86 ✅ x86_64 ✅ aarch64, arm, riscv64 Full support

Installation

zig fetch --save https://github.com/muhammad-fiaz/zon.zig/archive/refs/tags/0.0.3.tar.gz

or

for Nightly Installation, use this

zig fetch --save git+https://github.com/muhammad-fiaz/zon.zig.git

Then in your build.zig:

const zon_dep = b.dependency("zon", .{
    .target = target,
    .optimize = optimize,
});
exe.root_module.addImport("zon", zon_dep.module("zon"));

Quick Start

const std = @import("std");
const zon = @import("zon");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    // Optional: Disable update checking
    zon.disableUpdateCheck();

    // Create a new ZON document
    var doc = zon.create(allocator);
    defer doc.deinit();

    // Set values
    try doc.setString("name", "myapp");
    try doc.setBool("private", true);
    try doc.setInt("port", 8080);

    // Nested paths - auto-creates intermediate objects
    try doc.setString("dependencies.http.path", "../http");

    // Read values
    std.debug.print("Name: {s}\n", .{doc.getString("name").?});

    // Save to file
    try doc.saveAs("config.zon");
}

Supported ZON Syntax

zon.zig fully supports the build.zig.zon format:

.{
    .name = .zon,                        // Identifier as value
    .version = "0.0.3",                  // String
    .fingerprint = 0xee480fa30d50cbf6,   // Multi-bit hex handled as i128
    .minimum_zig_version = "0.15.0",
    .paths = .{                          // Array of strings
        "build.zig",
        "build.zig.zon",
        "src",
    },
    .dependencies = .{                    // Nested objects
        .http = .{
            .url = "https://example.com",
            .hash = "abc123",
        },
    },
}

Examples

Parse build.zig.zon

const source =
    \\.{
    \\    .name = .my_package,
    \\    .version = "0.1.0",
    \\    .paths = .{
    \\        "build.zig",
    \\        "src",
    \\    },
    \\}
;

var doc = try zon.parse(allocator, source);
defer doc.deinit();

// Read identifier value
const name = doc.getString("name"); // "my_package"

// Read array
const paths_len = doc.arrayLen("paths"); // 2
const first_path = doc.getArrayString("paths", 0); // "build.zig"

Find and Replace

var doc = zon.create(allocator);
defer doc.deinit();

try doc.setString("host1", "localhost");
try doc.setString("host2", "localhost");
try doc.setString("host3", "192.168.1.1");

// Find all paths containing "localhost"
const found = try doc.findString("localhost");
defer allocator.free(found);
// found.len == 2

// Replace all occurrences
const count = try doc.replaceAll("localhost", "production.example.com");
// count == 2

// Replace first occurrence only
const replaced = try doc.replaceFirst("old", "new");

// Replace last occurrence only
const replaced_last = try doc.replaceLast("old", "new");

Array Operations

// Create array and append
try doc.setArray("items");
try doc.appendToArray("items", "first");
try doc.appendToArray("items", "second");
try doc.appendIntToArray("numbers", 42);

// Read array
const len = doc.arrayLen("items"); // 2
const elem = doc.getArrayString("items", 0); // "first"

Pretty Print

// Default 4-space indentation
const output = try doc.toString();

// Custom indentation
const two_space = try doc.toPrettyString(2);

// Compact (no indentation)
const compact = try doc.toCompactString();

Merge and Clone

var base = zon.create(allocator);
try base.setString("name", "app");
try base.setInt("port", 8080);

var override = zon.create(allocator);
try override.setInt("port", 9000);
try override.setBool("debug", true);

// Merge override into base
try base.merge(&override); // Shallow merge
try base.mergeRecursive(&override); // Deep merge (merges nested objects)
// base now has port=9000, debug=true

// Deep equality
if (base.eql(&override)) { ... }

// Deep clone
var copy = try base.clone();
defer copy.deinit();

API Reference

Module Functions

Function Description
zon.open(allocator, path) Open existing ZON file
zon.create(allocator) Create new empty document
zon.parse(allocator, source) Parse ZON from string
zon.readFile(allocator, path) Read file into allocator-owned buffer
zon.writeFileAtomic(allocator, path, data) Write data atomically (tmp + rename)
zon.copyFile(source, dest, overwrite: bool) Copy a file (with optional overwrite)
zon.moveFile(old, new, overwrite: bool) Move/rename file (with optional overwrite)
zon.deleteFile(path) Delete a ZON file
zon.fileExists(path) Check if file exists
zon.disableUpdateCheck() Disable update checking

Document Methods - Getters

Method Description
getString(path) Get string value or null
getBool(path) Get bool value or null
getInt(path) Get integer value or null
getUint(path) Get u64 value or null
getFloat(path) Get float value or null
getNumber(path) Get number as float or null
toBool(path) Coerce value to boolean
isNull(path) Check if value is null
isNan(path) Check if value is NaN
isInf(path) Check if value is Inf
exists(path) Check if path exists
getType(path) Get base type name
getTypeName(path) Get precise type name

Document Methods - Setters

Method Description
setString(path, value) Set string value
setBool(path, value) Set bool value
setInt(path, value) Set integer value
setFloat(path, value) Set float value
setNull(path) Set value to null
setObject(path) Set empty object
setArray(path) Set empty array

Document Methods - Array Operations

Method Description
arrayLen(path) Get array length
getArrayString(path, index) Get string at index
getArrayElement(path, index) Get element at index
getArrayBool(path, index) Get boolean element
appendToArray(path, value) Append string to array
appendIntToArray(path, value) Append int to array
insertStringIntoArray(path, index, value) Insert string
insertIntIntoArray(path, index, value) Insert integer
removeFromArray(path, index) Remove from array
indexOf(path, value) Find string index
countAt(path) Count items/keys

Document Methods - Find & Replace

Method Description
findString(needle) Find paths containing string
findExact(needle) Find paths with exact match
replaceAll(find, replace) Replace all occurrences
replaceFirst(find, replace) Replace first occurrence
replaceLast(find, replace) Replace last occurrence

Document Methods - Other

Method Description
delete(path) Delete key, returns true if existed
clear() Clear all data
count() Get number of root keys
keys() Get all root keys
merge(other) Merge another document
clone() Create a deep copy
save() Save to original file path
saveAs(path) Save to specified path
saveAsAtomic(path) Atomically save to specified path (temporary file + rename)
saveWithBackup(backup_ext) Save and create a backup of the previous file using the extension
saveIfChanged() Only write when contents differ (normalizes trailing newline; returns bool)
toString() Get formatted ZON string
toCompactString() Get compact ZON string
toPrettyString(indent) Get ZON with custom indent
deinit() Free all resources
close() Alias for deinit()

Examples Directory

The examples/ directory contains comprehensive examples:

  • basic.zig - Core operations and getting started
  • package_manifest.zig - Parsing build.zig.zon format
  • find_replace.zig - Find and replace operations
  • arrays.zig - Array operations
  • pretty_print.zig - Pretty printing with different indentation
  • merge_clone.zig - Merging and cloning documents
  • config_management.zig - Configuration file management
  • file_operations.zig - Atomic writes, backups, and file helpers
  • identifier_values.zig - Identifier value parsing and usage
  • nested_creation.zig - Creating deeply nested structures
  • error_handling.zig - Examples of parse and file error handling

File helpers and utilities

Added file helpers for safer file operations:

  • zon.readFile(path, allocator) - Read file contents into allocator-managed buffer
  • zon.writeFileAtomic(path, contents) - Atomically write using a temporary file + rename
  • zon.copyFile(src, dest, overwrite) - Copy file with optional overwrite
  • zon.moveFile(src, dest, overwrite) - Move/rename file with optional overwrite
  • Document.saveAsAtomic(path) - Save a document atomically
  • Document.saveWithBackup(path) - Save and create a .bak backup of the previous file
  • Document.saveIfChanged() - Only write when contents differ (normalizes trailing newline; returns true if a write occurred)

Building

# Run tests
zig build test

# Build library
zig build

# Run example
zig build example

# Format code
zig fmt src/ examples/

Documentation

Full documentation: https://muhammad-fiaz.github.io/zon.zig/


Contributing

Contributions are welcome! Please read CONTRIBUTING.md.


License

MIT License - see LICENSE.


Links