Serde recursive struct deserialization

I have a recursive struct that I'm reading writing to an external system.
serialization / deserialization is done using serde, currently everything is derived like so:

#[derive(Serialize, Deserialize)]
struct Foo {
    bar: u64,
    baz: Vec<Foo>,
}

because the nesting can get very deep i would like to implement my own deserialization that avoids recursion and instead works iteratively.

I'm finding it hard to actually implement this using serdes visitor pattern however.
are there any examples of similar implementations or someone who could point me in the right direction?

Unless you also want a specific flat representation of your datastructure in the serde data model, there’s no way to avoid the recursion. A common approach for handling deep recursion nonetheless would be to make use of dynamic stack growth, e.g. through serde_stacker.


If you do prefer a flat representation, that’s of course possible. E.g. to name just one possibility I could come up with for your concrete example: you could represent a your nested Foo as a sequence of structs like

struct FooRoot {
    bar: u64,
    baz_count: usize,
}

and the baz_count represents how many similarly-encoded Foo follow in the sequence.

E.g.

Foo {
    bar: 42,
    baz: [
        Foo {
            bar: 100,
            baz: [
                Foo {
                    bar: 200,
                    baz: [],
                },
                Foo {
                    bar: 300,
                    baz: [
                        Foo {
                            bar: 400,
                            baz: [],
                        },
                    ],
                },
            ],
        },
        Foo {
            bar: 500,
            baz: [],
        },
    ],
}

would then be represented like

[
    FooRoot {
        bar: 42,
        baz_count: 2,
    },
    FooRoot {
        bar: 100,
        baz_count: 2,
    },
    FooRoot {
        bar: 200,
        baz_count: 0,
    },
    FooRoot {
        bar: 300,
        baz_count: 1,
    },
    FooRoot {
        bar: 400,
        baz_count: 0,
    },
    FooRoot {
        bar: 500,
        baz_count: 0,
    },
]
2 Likes