Skip to content

Instantly share code, notes, and snippets.

@nickelca
Last active December 28, 2024 08:25
Show Gist options
  • Save nickelca/bd4b636e9d0d9b99111fe1960dd5465e to your computer and use it in GitHub Desktop.
Save nickelca/bd4b636e9d0d9b99111fe1960dd5465e to your computer and use it in GitHub Desktop.
Parse json string into std.StringHashMap using std.json.parseFromSliceLeaky.
pub fn main() !void {
var arena_state: std.heap.ArenaAllocator = .init(std.heap.page_allocator);
defer arena_state.deinit();
const arena = arena_state.allocator();
const parsed = try std.json.parseFromSliceLeaky(Meow, arena,
\\{
\\ "name": "My name",
\\ "map": {
\\ "a": 1,
\\ "b": 2,
\\ "c": 3
\\ }
\\}
, .{});
_ = parsed;
}
const Meow = struct {
name: []const u8,
map: std.StringHashMap(u64),
pub fn jsonParse(
ally: std.mem.Allocator,
tokens: anytype,
opts: std.json.ParseOptions,
) std.json.ParseError(@TypeOf(tokens.*))!Meow {
if (try tokens.next() != .object_begin) {
return error.UnexpectedToken;
}
var name_opt: ?[]const u8 = null;
var map_opt: ?std.StringHashMap(u64) = null;
errdefer if (map_opt) |*map| map.deinit();
while (try tokens.peekNextTokenType() == .string) {
const key = try tokens.nextAllocMax(ally, .alloc_if_needed, opts.max_value_len.?);
if (std.mem.eql(u8, key.string, "name")) {
if (name_opt != null) switch (opts.duplicate_field_behavior) {
.use_last => {},
.use_first => continue,
.@"error" => return error.DuplicateField,
};
name_opt = try std.json.innerParse([]const u8, ally, tokens, opts);
} else if (std.mem.eql(u8, key.string, "map")) {
if (map_opt != null) switch (opts.duplicate_field_behavior) {
.use_last => {},
.use_first => continue,
.@"error" => return error.DuplicateField,
};
map_opt = .init(ally);
if (try tokens.next() != .object_begin) {
return error.UnexpectedToken;
}
while (try tokens.peekNextTokenType() == .string) {
const k = try std.json.innerParse([]const u8, ally, tokens, opts);
const v = try std.json.innerParse(u64, ally, tokens, opts);
try map_opt.?.put(k, v);
}
if (try tokens.next() != .object_end) {
return error.UnexpectedToken;
}
} else if (!opts.ignore_unknown_fields) {
return error.UnknownField;
}
}
if (try tokens.next() != .object_end) {
return error.UnexpectedToken;
}
if (name_opt == null or map_opt == null) {
return error.MissingField;
}
return .{
.name = name_opt.?,
.map = map_opt.?,
};
}
};
const std = @import("std");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment