Search code examples
rustdeserialization

Deserialize a vector written with debug trait formatting


Given a simple vector of vectors of usize, I can leverage the fact that Vec implements the Debug trait, and therefore use the {:?} formatter to pretty-print it (see playground):

let mut hierarchy: Vec<Vec<usize>> = Vec::new();
hierarchy.push(vec![0,1,2,3]);
hierarchy.push(vec![0,1]);
println!("Hierarchy: {:?}", hierarchy);

Assume that I write the output of println!(...) to a file. How can I easily deserialize it later?

E.g. my file looks like this:

[[0,1,2,3],[0,1]]

Using serde, I could serialize my data type and store it as (for example) JSON file. However, I don't need any "fancy" data format, just this plain vector of vectors. Is there any easy solution to deserialize according to the Debug trait ("reverse the printing")? Is there a simpler option than having to do all of the parser logic by hand, e.g. reading the file character by character looking for [, ] and ,?


Solution

  • Do not use the Debug trait for this purpose. It offers no guarantees that it is parseable, or that it is useful for any purpose at all.

    Derived Debug formats are not stable, and so may change with future Rust versions. Additionally, Debug implementations of types provided by the standard library (std, core, alloc, etc.) are not stable, and may also change with future Rust versions.

    std::fmt::Debug trait documentation

    There have been, for example, proposals for a compilation option that would make Debug never print anything at all, to avoid generating formatting code when code size is a priority. That might or might not ever happen, but it's allowed to happen; (Unfortunately I can't find a link to the recent one I remember; this is an older one.)


    serde_json is a perfectly good way to solve this problem:

    fn main() {
        let mut hierarchy: Vec<Vec<usize>> = Vec::new();
        hierarchy.push(vec![0, 1, 2, 3]);
        hierarchy.push(vec![0, 1]);
        serde_json::to_writer(std::io::stdout(), &hierarchy).unwrap();
    }
    

    will print [[0,1,2,3],[0,1]]. You don't need any setup.

    If you care about using more Rust-like syntax, you can use ron, a general purpose serializer that uses a Rust-like notation; or uneval which generates actual Rust code, but you'll need a Rust compiler to "deserialize" it.