I read this but did not get it.
I've the below code that is parsing a JSON string into a struct correctl, I'm trying to do the opposite, that is stringifying a struct as a json string, but looks i'm taking a wrong approach:
const std = @import("std");
const my_json =
\\{
\\ "vals": {
\\ "testing": 1,
\\ "production": 42
\\ },
\\ "uptime": 9999
\\}
;
const Config = struct {
vals: struct {
testing: u8,
production: u8,
},
uptime: u64,
};
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
defer if (gpa.deinit() != .ok) {
std.log.err("We got a leack", .{});
} else {
std.log.debug("memory managed correctly", .{});
};
const config = try std.json.parseFromSlice(Config, allocator, my_json, .{});
defer config.deinit();
std.log.info("{}", .{config.value.vals.testing});
std.log.info("{}", .{config.value.vals.production});
std.log.info("{}", .{config.value.uptime});
const config2 = try std.json.parseFromSlice(std.json.Value, allocator, my_json, .{});
defer config2.deinit();
std.log.info("production: {}", .{config2.value.object.get("vals").?.object.get("production").?.integer});
var conf3 = Config{
.vals = .{
.testing = 2,
.production = 48,
},
.uptime = 15,
};
std.log.info("conf3 {any}", .{conf3});
var string = std.ArrayList(u8).init(allocator);
defer allocator.free(string);
if (std.json.stringify(conf3, .{}, string.writer())) |json| {
std.log.info("json: {any}", .{json});
} else |err| {
std.log.err(" {any}", .{err});
}
}
I got the error:
/usr/lib/zig/std/mem/Allocator.zig:307:45: error: access of union field 'Pointer' while field 'Struct' is active
const Slice = @typeInfo(@TypeOf(memory)).Pointer;
~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
/usr/lib/zig/std/builtin.zig:228:18: note: union declared here
pub const Type = union(enum) {
^~~~~
I found the answer, I should be using stringifyAlloc
as:
if (std.json.stringifyAlloc(allocator, conf3, .{})) |json| {
defer allocator.free(json);
std.log.info("json: {s}", .{json});
} else |err| {
std.log.err(" {any}", .{err});
}
Now my full running code is:
// curl -X GET "https://httpbin.org/get" -H "accept: application/json"
// Zig version: 0.11.0
const std = @import("std");
const my_json =
\\{
\\ "vals": {
\\ "testing": 1,
\\ "production": 42
\\ },
\\ "uptime": 9999
\\}
;
const Config = struct {
vals: struct {
testing: u8,
production: u8,
},
uptime: u64,
};
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
defer if (gpa.deinit() != .ok) {
std.log.err("oh no, we've got a leak", .{});
} else {
std.log.debug("memory managed correctly", .{});
};
const config = try std.json.parseFromSlice(Config, allocator, my_json, .{});
defer config.deinit();
std.log.info("{}", .{config.value.vals.testing});
std.log.info("{}", .{config.value.vals.production});
std.log.info("{}", .{config.value.uptime});
const config2 = try std.json.parseFromSlice(std.json.Value, allocator, my_json, .{});
defer config2.deinit();
std.log.info("production: {}", .{config2.value.object.get("vals").?.object.get("production").?.integer});
var conf3 = Config{
.vals = .{
.testing = 2,
.production = 48,
},
.uptime = 15,
};
std.log.info("conf3 {any}", .{conf3});
if (std.json.stringifyAlloc(allocator, conf3, .{})) |json| {
defer allocator.free(json);
std.log.info("json: {s}", .{json});
} else |err| {
std.log.err(" {any}", .{err});
}
}
And got the output correctly as:
info: 1
info: 42
info: 9999
info: production: 42
info: conf3 json.Config{ .vals = json.Config.Config__struct_4384{ .testing = 2, .production = 48 }, .uptime = 15 }
info: json: {"vals":{"testing":2,"production":48},"uptime":15}
debug: memory managed correctly