#Acceptable string format for stringified JSON

1 messages · Page 1 of 1 (latest)

median pivot
#

I usually test my code on https://zig-play.dev, and I came upon this error:

An error occurred:
/usr/local/bin/lib/std/fmt.zig:458:5: error: invalid format string 's' for type 'void'
    @compileError("invalid format string '" ++ fmt ++ "' for type '" ++ @typeName(@TypeOf(value)) ++ "'");
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
referenced by:
    formatType__anon_6398: /usr/local/bin/lib/std/fmt.zig:489:38
    format__anon_6386: /usr/local/bin/lib/std/fmt.zig:183:13
    remaining reference traces hidden; use '-freference-trace' to see all reference traces

Here's my reference code. I found changing {s} (what we usually use for strings) to {any} solves it, but what other acceptable string formats are there for handling this? For reference, json.stringify() can return a void which seems to be what it trips over.

const std = @import("std");
const json = std.json;
const outWriter = std.io.getStdOut().writer();

pub fn main() !void {
  const Foo = struct {
    bar: usize,
    baz: []const u8
  };
  const foo = Foo{ .bar = 5, .baz = "hello" };
  const testJson = try json.stringify(foo, .{ .string = .Array }, outWriter);
  
  std.debug.print("{any}", .{testJson}); // we originally use {s}
}
#

Maybe I could use the ++ operator instead to conjoin it, but that doesn't seem to be a valid method either 😦

manic viper
#

I think where you're getting confused is that json.stringify() doesn't return the string, it writes it to the out_stream. When a function returns E!void , the void means "no value".

In your case the JSON string is already written to stdout. If you want to capture it into a buffer and inspect it later, you have to use a buffered writer, which a std.ArrayList(u8) can do for you if you want

#

About the {s} specifier, that is really only used (as far as I know) to tell a formatter how to handle slices/arrays of u8. s means to render the whole slice/array a string, and any means "render this thing as a list of numbers"

#

But in your case, as mentioned, you're actually trying to print a void (a nothing), for which the s specifier doesn't apply

#

Last note, the ++ operator only works on arrays (not slices) and even then they must be known at comptime -- so for example, string literals, e.g.
var s = "hello" ++ " other";

#

Hope that wasn't TMI!

median pivot
#

All good! Yeah it helps a lot more. I'm curious if there's a way to coerce the value return to a string without the any specifier

#

I assumed any was a compiler guess to make whatever it took work in a string format

#

When I looked into the function more, I think I should've used .string = StringOutputOptions logic instead to handle the u8 format. Thanks for the answer though!

manic viper
#

Sure thing! BTW most of time you can omit the specifier and just put {} in a fmt string. Most types have a default rendering format, mainly []const u8 needs disambiguation