ZON field value extractor (for the lack of better name) - zon_get_fields

A while ago I was looking for a way to use ZON as a configuration fie format, and found none. The parsing itself was there (std.zig.Ast.parse()), but getting the values from the Ast required a considerable amount of work.

Well, since I did that work, why not share it with the world? So, here it is -

The thing is not optimal, since each call of a getFieldVal*() function has to split the provided path and walk the AST, but at least it works.

Also, there’s this strange thing with negative field values represented by two tokens in AST, the first being “-”, and the next containing the digits. I hope the way I’m reading them (getting “-”, and then getting the next token, here) is correct in the long run, but honestly, I don’t know, and it doesn’t sit well with me.

Update 2023-12-31:

  1. Switched from several getFieldVal* functions to one public function - getFieldVal;
  2. Added support for proper parsing of character literals (although not Unicode literals at this time);
  3. Updated example code in README.

Happy New Year everyone!

Update 2024-01-25: Added a new function (template), which fills your arbitrary struct with values from the provided AST - pub fn zonToStruct.

Update 2024-01-28: Unicode character literals are now supported.

Update 2024-02-22: pub fn zonToStruct now returns an auto-generated struct with fields that indicate whether their corresponding fields in the target struct were filled or not. Previously there was no way to tell.


This is a big update, kinda, so I thought I’d give the thread a bump. Hope it’s not inappropriate.

Anyway, I’ve added a completely new way of getting values from the ZON text - you can now throw (a pointer to) your struct and an AST at this new function - pub fn zonToStruct, and thanks to Zig comptime magic (mutually recursive comptime calls… my head nearly exploded), it comes out all filled with values!

Well, at least if the AST contains the values for your struct fields. When there’s no match, the field is not modified, and I couldn’t figure out a way to report this back to the caller, which is a bummer :frowning_face:


You could have a optional comptime out parameter in the zonToStruct function that fills in the missing field information. At some point I think this PR might get merged into std as well WIP: zon by MasonRemaley · Pull Request #17731 · ziglang/zig · GitHub

1 Like

You mean, like an optional second struct, with the same field names, but boolean (true - target struct field modified, false - not modified)?

I guess that is one way of doing it, but I think it would be a pain to implement, and most importantly, to use.

I’m considering providing field mandatory / optional information to zonToStruct, in some form, and making it return error if a mandatory field was not found. In essence, a schema (see JSON schema, XML schema, etc.), in a simplified form.

I was also thinking about returning the number of fields that were not modified as a simpler (temporary?) solution, maybe.

I was more like thinking of out parameter like missing_fields that contains array of enum literals which are the names of the missing fields

You may be interested in seeing how getty does in-band and out-band metadata for your second idea: Customization - Getty


So, once again, a major update - pub fn zonToStruct now returns an auto-generated struct with fields that indicate whether their corresponding fields in the target struct were filled or not. Previously there was no way to tell if the field was assigned to or not.

At first I was thinking about a lightweight (no conditionals, etc.) schema, but then I thought it’s too much hassle for the user, and for me, and that they can simply check the result and decide whether it’s OK or not.

Fields of this “report” struct are enums of ZonFieldResult type - unless they are sub-structs, arrays, arrays of sub-structs, arrays of arrays, that ultimately end up being composed of the same ZonFieldResult enums.

They can indicate either that the field was not_filled or filled, and in the case of arrays - if there was not enough values in ZON / AST (partially_filled) or too many values (overflow_filled).

Slices are either not_filled or filled, simple , since fn zonToStruct has to allocate them dynamically anyway, there’s no such thing as not enough values or too many. A slice represented with one ZonFieldResult field in the report struct.
Sadly, this means that if it’s a slice of structs, for example, you don’t get information on the individual fields of these structs. Oh well, maybe in the future I’ll come up with something to remedy this.

In the meantime, I think I’ll take a break from this little project.

1 Like