fork of gitlab.com/devnw/zig/json for zig 0.17

Files
README.md

json #

A fully RFC 8259 compliant JSON library for Zig 0.16.0 with JSON Schema 2020-12 validation.

Build Status

Status #

Aspect Info
API Stability Beta
Zig Version 0.16.0+
Platforms Linux, macOS, Windows

Features #

  • RFC 8259 Compliant Parsing - Strict JSON parsing with proper error handling
  • JSON Schema 2020-12 Validation - Full draft support with ECMA-262 regex
  • Type-Safe Encoding - Encode any Zig type to JSON with comptime reflection
  • Streaming Output - Writer-based API for memory-efficient encoding
  • Pretty Printing - Configurable indentation and formatting
  • Normalized Numbers - Exact decimal representation without floating-point errors
  • Unicode Support - Full UTF-8 and surrogate pair handling
  • Zero External Dependencies - Pure Zig implementation

Installation #

Add to your build.zig.zon:

.dependencies = .{
    .json = .{
        .url = "https://gitlab.com/devnw/zig/json/-/archive/main/json-main.tar.gz",
        // Add hash after first fetch
    },
},

Then in your build.zig:

const json = b.dependency("json", .{
    .target = target,
    .optimize = optimize,
});

exe.root_module.addImport("json", json.module("json"));

Quick Start #

Parse JSON #

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

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

    const input =
        \\{"name": "json", "version": 1}
    ;

    var err = json.ParseError.init();
    var doc = try json.parse(allocator, input, .{}, &err);
    defer doc.deinit();

    // Access parsed values
    for (doc.root.obj) |member| {
        std.debug.print("{s}: ", .{member.k});
        switch (member.v) {
            .str => |s| std.debug.print("{s}\n", .{s}),
            .num => |n| std.debug.print("{s}\n", .{n.lexeme}),
            else => std.debug.print("...\n", .{}),
        }
    }
}

Encode Zig Types #

const Point = struct { x: i32, y: i32 };
const point = Point{ .x = 10, .y = 20 };

// Minified output
const output = try json.encode(allocator, point, .{});
defer allocator.free(output);
// {"x":10,"y":20}

// Pretty printed
const pretty = try json.encode(allocator, point, .{ .indent = "  " });
defer allocator.free(pretty);
// {
//   "x": 10,
//   "y": 20
// }

Validate with JSON Schema #

const schema_json =
    \\{
    \\  "type": "object",
    \\  "required": ["name"],
    \\  "properties": {
    \\    "name": {"type": "string"},
    \\    "age": {"type": "integer", "minimum": 0}
    \\  }
    \\}
;

var err = json.ParseError.init();

// Compile schema
var schema_doc = try json.parse(allocator, schema_json, .{}, &err);
defer schema_doc.deinit();

var compiled = try json.compileSchema(allocator, &schema_doc, .{}, null, &err);
defer compiled.deinit();

// Validate instance
var data_doc = try json.parse(allocator, "{\"name\": \"Alice\"}", .{}, &err);
defer data_doc.deinit();

const report = try json.validate(allocator, &compiled, data_doc.root, .{});
defer allocator.free(report.errors);

if (report.ok) {
    std.debug.print("Valid!\n", .{});
}

Documentation #

Supported Types for Encoding #

Zig Type JSON Output
bool true / false
integers Number
floats Number (NaN/Inf → null)
[]const u8 String
?T Value or null
enum String (tag name)
struct Object
tuple Array
[]T, [N]T Array
union(enum) {"tag": value}

Building #

# Build the library
zig build

# Fetch the JSON Schema Test Suite (not vendored) at the commit CI pins.
# test-schema and test-all fail, naming this command, until it has run.
scripts/fetch-json-schema-test-suite.sh

# Run all tests
zig build test-all --summary all

# Individual test suites
zig build test          # Unit tests
zig build test-accept   # Acceptance tests
zig build test-data     # Edge case tests
zig build test-schema   # JSON Schema test suite

# Generate documentation
zig build docs

Project Structure #

json/
├── src/
│   ├── json.zig        # Main library interface
│   ├── parser.zig      # RFC 8259 parser
│   ├── emitter.zig     # Value stringification
│   ├── encode.zig      # Zig type encoding
│   ├── schema.zig      # JSON Schema validator
│   ├── number.zig      # Decimal number handling
│   ├── unicode.zig     # UTF-8 utilities
│   ├── pointer.zig     # JSON Pointer (RFC 6901)
│   └── regex_ecma262.zig # Pattern validation
├── tests/
│   ├── accept.zig      # Acceptance tests
│   ├── testdata.zig    # Edge case tests
│   └── schema_suite.zig # JSON Schema test suite
├── docs/               # Documentation
├── testdata/           # Test fixtures
└── build.zig

Specifications #

This library implements:

Roadmap #

Key planned features (see full roadmap):

Feature Priority Issue
JSON to Zig type unmarshaling Critical #7
Streaming tokenizer High #8
Custom marshaler interface High #9
Struct field tags High #10
Time/Duration support High #11

Cross-Platform Support #

Platform Status
Linux x86_64 ✅ Tested
Linux ARM64 ✅ Tested
macOS ARM64 ✅ Tested
macOS x86_64 ✅ Tested
Windows x86_64 ✅ Tested
FreeBSD x86_64 ✅ Builds
NetBSD x86_64 ✅ Builds

Contributing #

Contributions are welcome! Please check the issue tracker for open tasks.

  1. Pick an issue or create one for your feature
  2. Fork the repository
  3. Create your feature branch
  4. Add tests for new functionality
  5. Submit a merge request

License #

Apache-2.0 License - See LICENSE for details.