# Parsing recursive (two-layer) JSON object

**URL:** <https://ziggit.dev/t/parsing-recursive-two-layer-json-object/16031>\
**Category:** Help\
**Tags:** language, standard-library\
**Created:** [June 8, 2026, 10:22pm UTC](https://ziggit.dev/t/parsing-recursive-two-layer-json-object/16031 "2026-06-08T22:22:21Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![g1rly-c0d3r](https://ziggit.dev/user_avatar/ziggit.dev/g1rly-c0d3r/32/8578_2.png) [@g1rly-c0d3r](https://ziggit.dev/u/g1rly-c0d3r)\
**Post date:** [June 8, 2026, 10:22pm UTC](https://ziggit.dev/t/parsing-recursive-two-layer-json-object/16031/1 "2026-06-08T22:22:21Z")

</div>

Sorry in advance for the lack of snippets, im writing this from my phone on the bus.  
I am trying to parse a JSON object with two fields: a number (which is an enum) and another JSON object. The issue is that the inner object’s fields are dependent on the number, with almost no overlapping fields. My initial guess was to use a tagged union on the number, but `json.parseFromSlice` returns `error.UnexpectedToken`.

The repo is [gitlab.com/g1rly-c0d3r/obs-ws.git](http://gitlab.com/g1rly-c0d3r/obs-ws.git) if it will be helpful. (apologies if the visibility is private, I will update once i get home)

---

<div class="post-metadata">

**Author:** ![johan\_alley](https://ziggit.dev/letter_avatar_proxy/v4/letter/j/c68b51/32.png) [@johan\_alley](https://ziggit.dev/u/johan_alley)\
**Post date:** [June 8, 2026, 11:19pm UTC](https://ziggit.dev/t/parsing-recursive-two-layer-json-object/16031/2 "2026-06-08T23:19:48Z")

</div>

a custom jsonParse function is a way to do it I guess?

```zig
const Foo = struct { a: u32 };
const Bar = struct { b: []const u8 };

const Payload = union(enum) {
    foo: Foo,
    bar: Bar,

    pub fn jsonParse(allocator: std.mem.Allocator, source: anytype, options: std.json.ParseOptions) !Payload {
        if (try source.next() != .object_begin) return error.UnexpectedToken;

        _ = try source.next();
        const num = switch (try source.next()) {
            .number => |s| try std.fmt.parseInt(u8, s, 10),
            else => return error.UnexpectedToken,
        };

        _ = try source.next();
        const result: Payload = switch (num) {
            0 => .{ .foo = try std.json.innerParse(Foo, allocator, source, options) },
            1 => .{ .bar = try std.json.innerParse(Bar, allocator, source, options) },
            else => return error.UnexpectedToken,
        };

        if (try source.next() != .object_end) return error.UnexpectedToken;
        return result;
    }
};

```
