#Parsing JSON from example causing "cannot format optional without a specifier" error

1 messages · Page 1 of 1 (latest)

bronze linden
#

Totally new to Zig (or C etc)
I'm trying to parse some JSON from webUI via this example:
https://zig.guide/master/standard-library/json
I believe the error has to do with the !void union result
Removing the try and the union (the "guts"), removes the error for the main function but I can't connect the compiler errors with that.

Bind the webUI event receiver to my parser function (in main.zig)
_ = try win.binding("send_project_from_webui", proj.get_project_from_webui);

Event receiver function
pub fn send_project_from_webui(e: *webui.Event) void { const json = e.getString(); _ = json; }

Parser function
`pub fn get_project_from_webui(json: []const u8) !void {

const Setup = struct {
  proj_name: []const u8,
  proj_bpm: u16,
  created: u32,
  last_saved: u32
};

const allocator = std.heap.page_allocator;

const json_tree = try std.json.parseFromSlice(Setup, allocator, json, .{});
defer json_tree.deinit();

const json_val = try json_tree.value;
const proj_name = json_val.proj_name;

std.debug.print("\n\nPROJ_NAME{s}\n\n", .{proj_name});

}
`

The error...

Let's parse a JSON string into a struct type, using the streaming parser.

#

The error
/usr/lib/zig/std/fmt.zig:532:17: error: cannot format optional without a specifier (i.e. {?} or {any}) @compileError("cannot format optional without a specifier (i.e. {?} or {any})"); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usr/lib/zig/std/fmt.zig:193:23: note: called from here try formatType( ~~~~~~~~~~^ /usr/lib/zig/std/fmt.zig:1815:11: note: called from here format(counting_writer.writer().any(), fmt, args) catch unreachable; ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usr/lib/zig/std/fmt.zig:1859:83: note: called from here pub inline fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [count(fmt, args):0]u8 { ~~~~~^~~~~~~~~~~ /home/ee/.cache/zig/p/zig_webui-2.5.0-beta.4-M4z7zZBVAQDzkq-5npSyZ-m9MKyMlEb5fIQA5PZahJyz/src/webui.zig:777:46: note: called from here const err_msg = std.fmt.comptimePrint( ~~~~~~~~~~~~~~~~~~~~~^ referenced by: main: src/main.zig:21:24 main: /usr/lib/zig/std/start.zig:660:37

summer ledge
#

problem seems completely unrelated to the use of an error union (!void)

the very final problem is: cannot format optional without a specifier (i.e. {?} or {any}), which would suggest you have something like:

const value: ?u8 = 123;
std.debug.print("{}", .{value});

where, instead of {}, you should have {?} or {any} (as error message already suggested)

error also points at src/main.zig:21:24, should check that line, i have no idea what it contains

bronze linden
#

Thanks

Line 21 is the binding shown above
I'm wondering if inside webUI something is trying to print; related to the binding
Like the "zig function" that the "webUI" function is bound to cannot return a union
Maybe because webUI has some print statment that expects a specific return?

I don't have any undefined print {} values in my code

Again, the reason I point at the union is that removing it (and the try) makes the code compile

#

e.g. this line....
const err_msg = std.fmt.comptimePrint(

summer ledge
#

ok, so the problem would be that the library calling/interacting with your code is doing some (wrong) code for diagnostics/printing message

#

this is exactly where it is failing

#

didn't notice this was some kind of "callback" code, and you weren't calling your function yourself before

bronze linden
#

Got it. I'll check in on Github

#

I may try to add a third "stepping stone" function to obviate the problem

#

This may be the way they expect it done

summer ledge
#

IIRC, return_type is a ?type (but it actually is never null), the library code should probably be doing const Return = fnInfo.return_type orelse @compileError("unreachable") to begin with

#

which would explain why comptimePrint fails with "this is an optional and you aren't printing as such"

#

TIL you can do {} + T in comptimePrint (was using {s} + @typeName(T)) by looking at this, thanks 🙂

bronze linden
#

Thanks again
A bit lost on this. It seems like the lib needs to change?
Or is there something you recommend I do in my code to resolve

summer ledge
#

if you haven't done so yet, i would send them an isue (or even PR), given it is an easy thing to get fixed 😉

bronze linden
#

Yes.That is my plan

summer ledge
#

but there is a bug on their code for how to check such constraint + report the error to you

bronze linden
#

Yep. got that
Just not clear on the best way to ensure I send void

#

Again, I was just going to add an extra function that calls the "real" function
But this sound...eh

summer ledge
#

if my theory is correct, you just need to patch the library as:```diff
const fnInfo = TInfo.@"fn";
// Verify return type is void

  • const Ret = fnInfo.return_type orelse @compilerError("return_type can't be null");
  • if (fnInfo.return_type != void) {
  • if (Ret != void) {
    const err_msg = std.fmt.comptimePrint(
    "callback's return type ({}), it must be void!",
  •       .{fnInfo.return_type},
    
  •       .{Ret},
      );
      @compileError(err_msg);
    
    }
#

and definitely, change your function's signature

bronze linden
#

Ty

summer ledge
#

if that provides a readable message when your return is !void, send them a PR

bronze linden
#

Just a note per the patch: it needed '@compileError' not @compilerError
But other than that, it seems to be working as intended. Thanks for the detailed fix
We'll see what they say 🙂