Hocon for zig


I would like to show you what I have been working on over summer and mostly during my evenings after work.

A HOCON parser for Zig: GitHub - lejmr/zig-hocon: HOCON (Human-Optimized Config Object Notation) parser for Zig · GitHub

The whole idea behind it is to have a superior configuration layer for my future applications where json, toml, or yaml can not stand. Speaking about complicated configuration files where you want to reuse configuration sections across multiple environments or configuration variants.

The interface tends to be pretty standard: 1) you define your target structure 2) you load it.

const Server = struct {
    host: []const u8,
    port: u16 = 8080,
    level: enum { debug, info } = .info,
};

const parsed = try hocon.parseFromSlice(Server, gpa, 
    \\host = example.org
    \\level = debug
);
defer parsed.deinit();

It’s early. Parsing, dotted keys, merging, concatenation and conversion into
structs work; includes and substitutions don’t yet, so most real
application.conf files won’t load today.

Important part of the repo is conformance suite which turns specification into data points. I kept arguing with myself about what HOCON.md actually says, so I turned it into a test suite. Reference is obviously lightbench/config which I am checkinng against + HOCON.md specification. Current state of the art against the conformance suite gives:

vs spec vs typesafe/config
typesafe/config 1.4.9 89% 99%
pyhocon 0.3.63 71% 67%
zig-hocon 57% 59%

The Java one surprised me — it disagrees with its own spec in 43 places, and
some of those I’ve been sending as PRs to lightbend/config. The suite is plain
data, so any HOCON parser can be plugged in with a small adapter.

I’d love to hear whether mirroring std.json feels right to you, and what you use for config in Zig today.

Do you need zon interface?

Supported Zig versions

0.16.0.

AI / LLM usage disclosure

The parser itself — tokenizer, parser, value graph, conversion and the public
API — is written by hand; learning Zig was the point. I used Claude for the
tooling around it: the oracle wrappers, the conformance runner and report
generator, and drafting part of the conformance cases. Expected values never
come from a model — they come from running typesafe/config and are then checked
by hand against the spec text. Claude also helped me edit the README, and a lot of other boring parts.

2 Likes

If its goal is human readability, it would be good to post an example of that, so I can see that the claim has some validity.

1 Like

Fair point.

In general the HOCON syntax allows you to write JSON-like structure, but in the text where types are not enforced you can write practically anything. You can build blocks or use period-notation:

# defaults shared by every environment
server {
  host = example.org
  port = 8080
  timeout = 30s
}

database {
  url = "postgres://localhost/app"
  pool.max = 10
}

# production overrides only what differs
server.port = 443
database.pool.max = 50

No quotes around simple strings, no commas, comments, and the later
server.port merges into the block above instead of replacing it. This part
works in zig-hocon today: hocon file.conf to get JSON format, but you will use most of the time Zig programatic API.

{
  "server": {
    "host": "example.org",
    "port": 443,
    "timeout": "30s"
  },
  "database": {
    "url": "postgres://localhost/app",
    "pool": {
      "max": 50
    }
  }
}

What makes it really pay off across environments are includes and substitutions:

include "defaults.conf"
database.url = ${DATABASE_URL}

Basically, you can have some files with shared config sections and in consuming files you can simply override only important parts.

—-
The resolution is working on my computer, but soon will be in git for all

Update: substitutions resolve

As mentioned in my last reply, substitutions are now in main: ${a.b}, ${?a} which updated coverage over internal conformance test suite.

As I was facing several technical difficulties and made some decisions, I ended with a need to formalize the decision outside the source code, so I wrote following two articles:

1 Like