How to parse json object with string arrays as values

Hello friends of zig,

I’m trying to parse a JSON payload that looks like this:

{"topology": { "n1": ["n2", "n3"], "n2": ["n1", "n3"] }}

The number and name of keys is dynamic.

I’m using std.json.parseFromSlice and a struct like this:

const topology = struct {
  // ... some stuff omitted 
  topology: std.json.ArrayHashMap([]u8),
}

But it refuses to parse the json with error: InvalidCharacter. I’ve boiled it down to std.json.ArrayHashMap not being able to deserialize string arrays:

test "parse object with string array values" {
    var debug_allocator = std.heap.DebugAllocator(.{}){};
    defer _ = debug_allocator.deinit();
    const allocator = debug_allocator.allocator();

    const json =
        \\{"k1": ["foo", "bar"], "k2":[]}
    ;

    const parsed = try std.json.parseFromSlice(std.json.ArrayHashMap([]u8), allocator, json, .{});
    defer parsed.deinit();
}

Which fails with:

/opt/homebrew/Cellar/zig/0.14.0_1/lib/zig/std/fmt.zig:1782:24: 0x104711bf3 in charToDigit (test)
    if (value >= base) return error.InvalidCharacter;
                       ^
/opt/homebrew/Cellar/zig/0.14.0_1/lib/zig/std/fmt.zig:1647:23: 0x104710d77 in parseIntWithSign__anon_13054 (test)
        const digit = try charToDigit(math.cast(u8, c) orelse return error.InvalidCharacter, buf_base);
                      ^
/opt/homebrew/Cellar/zig/0.14.0_1/lib/zig/std/fmt.zig:1535:5: 0x1046e370f in parseIntWithGenericCharacter__anon_9205 (test)
    return parseIntWithSign(Result, Character, buf, base, .pos);
    ^
[...]

So, am I doing this the right way? I’ve toyed a little with different value types for ArrayHashMap to no avail. Is that something that’s missing in the standard library or maybe a bug?

But that’s not a slice of strings, that’s a slice of u8s (which is why it’s trying to parse ints here).
[][]u8 is probably the type you want.

2 Likes

Ooff… well, I’m officially an idiot. :smiley: Thanks, that’s all it was. :heart:

2 Likes