ZON Schema

Does ZON need ZON-schema (like JSON-schema for JSON)?

What would ZON-schema look like? Just a zig struct definition?

Just a struct definition as schema does not cover build.zig.zon. Though this is perhaps a flaw of the current design of build.zig.zon (that it is not easily runtime-representable in zig’s type system):

And we may want to think a little bit about how schema evolution can best be accomplished by users, or how it can be made easier for users to accomplish schema evolution.

Honestly, we could get zon-schema for free (using zig struct definitions) by just re-considering the current design of build.zig.zon to not require effectively a map type. Though I am not sure how I feel about disallowing map types in zon-schema.

You won’t need to maintain a ZON schema when importing ZON files without a result type (will be available in 0.14.1), including for build.zig.zon, since package manifest’s schema isn’t meant to be maintained by the user.

If you still want to maintain a ZON schema for some src/data.zon in Zig source code as a file struct, then the solution could be a new zq feature.

For instance, to check your schema you’d run:

zq schema src/Data.zig src/data.zon
# or `zq` could automatically look for the zon file in the same path
zq schema src/Data.zig

Also, to update your schema you’d run:

zq schema --update src/Data.zig src/data.zon
# or `zq` could automatically look for the zon file in the same path
zq schema -u src/Data.zig

Well that would be an invisible, schema-on-write, compile-time only feature which is quite limiting.

I guess we could use file-structs as schema:

MySchema.zig:

my_num_field: u8,
my_str_field: [] const u8,

But the question still stands about what to do about map types like dependencies in build.zig.zon:

dependencies: std.StringArrayHashMapUnmanaged(Dependency),

It might also be arduous for language interop to require a full AST parser thing for zon-schema file-structs like this:

my_num_field: u8,
my_str_field: [] const u8,
my_struct_field: MyStructField,

const MyStructField = struct {
    another_num: u8,
};

But the question still stands about what to do about map types like dependencies in build.zig.zon

Since ZON doesn’t have map types, they’ll have to be used directly:

const data: @import("Data.zig") = @import("data.zon");
const value = data.map.key1.value;

It might also be arduous for language interop to require a full AST parser thing for zon-schema file-structs

Yeah, projects in other languages will want to use a ZON parser implemented in their language, just like they do for JSON. And use zq to maintain the Zig file struct/ZON data schema pair.

UPD (sorry for editing so much – just woke up):

Oh, you meant that they won’t be able to parse the Zig file struct schema, because that requires a Zig AST parser. Yeah, that’s true.

Parsing a zon-schema only requires a subset of zig syntax and can ignore anything that isn’t a type definition.
That ofc requires that the zon-schema types are written by hand, but that will be done the majority of the time anyway.

1 Like

I’ve been able to add ZON schema generation to zq:

For instance, here’s how to generate this Build.zon.zig schema from this build.zig.zon (or, see gen step):

# you can also specify other types, see `zq -h`
zq schema -e "name = enum { zq }" build.zig.zon 

For a more general example see generateSchema test.

I’m also planning to add support for:

  • Type checking enum literals.

  • Converting array’s with simple literal elements of the same type to slices, instead of structs.

1 Like

We could use top-level doc comment to specify a path or other URI to a schema file, which would enable editor completion support for ZON config files:

my_config.zon:

//! my_schema.zig
.{}

3 Likes

Currently this is invalid syntax in ZON, and needs changes in the language to enable it. So probably .@“$schema” field would be the best bet. And then the ZLS or anything in the code editor will take out the struct from defined URL or file, parse it, get the AST, and then provide auto completion and docs for field taken from the struct as well.