Search code examples
rustserdetoml

How do I parse a TOML file with a table at the top level into a Rust structure?


For example:

#[macro_use]
extern crate serde_derive;
extern crate toml;

#[derive(Deserialize)]
struct Entry {
    foo: String,
    bar: String,
}

let toml_string = r#"
  [[entry]]
  foo = "a0"
  bar = "b0"

  [[entry]]
  foo = "a1"
  bar = "b1"
  "#;
let config: toml::value::Table<Entry> = toml::from_str(&toml_string)?;

However, this does not work and throws an error about unexpected type argument for Table.


Solution

  • Printing the arbitrary parsed value shows you what structure you have:

    let config: toml::Value = toml::from_str(&toml_string)?;
    println!("{:?}", config)
    

    The reformatted output shows that you have a table with a single key entry which is an array of tables with the keys foo and bar:

    Table({
      "entry": Array([
        Table({
          "bar": String("b0"),
          "foo": String("a0")
        }),
        Table({
          "bar": String("b1"),
          "foo": String("a1")
        })
      ])
    })
    

    When deserializing, you need to match this structure:

    #[derive(Debug, Deserialize)]
    struct Outer {
        entry: Vec<Entry>,
    }
    
    #[derive(Debug, Deserialize)]
    struct Entry {
        foo: String,
        bar: String,
    }
    
    let config: Outer = toml::from_str(&toml_string)?;