How to deserialize nested toml-structures into custom structs?

Good evening fellow Rustaceans,

I am currently trying to do small first steps into Rust but can't seem to get deserializing anything else than most basic toml-structures into custom structs right. I think I don't fully understand the way toml-rs parses e.g. nested structures into custom structs and could use some help.

Suppose I got this .toml-file:

balls = 5
bricks = 250
[cars]
  [cars.car1]
  color = "green"
  speed = 3
  [cars.car2]
  color = "red"
  speed = 10
[trucks]
  [trucks.truck1]
  load = 15
  hp = 670
  [trucks.truck2]
  load = 25
  hp = 800

Where all (sub-)sections are required, e.g. no Option<...> to keep it simple. How would a custom structure look that this .toml could be deserialized to? I tried the following, but this does not work:

struct Toys {
  balls: u8,
  bricks: u8,
  cars: Cars,
  trucks: Trucks,
}

struct Cars {
  cars: Vec<Car>,
}

struct Trucks {
  trucks: Vec<Truck>,
}

struct Car {
  color: String,
  speed: u8,
}

struct Truck {
  load: u16,
  hp: u16,
}

This produces runtime errors when I try to deserialize the example .toml into this structure-setup. What would I need to change in order to deserialize the nested parts correctly? Where am I thinking wrong at the moment?

Best,
Daniel

I'm not sure exactly how far you got to, but what you have is pretty close, except that the rust representation for that toml would use a HashMap<String,Car> for cars and a similar construct for trucks (ie cars and trucks are a map instead of a vector). Here's a working example

playground

use serde::Deserialize;
use std::collections::HashMap;
use toml;
#[derive(Debug, Deserialize)]
struct Toys {
    balls: u8,
    bricks: u8,
    cars: HashMap<String, Car>,
    trucks: HashMap<String, Truck>,
}

#[derive(Debug, Deserialize)]
struct Car {
    color: String,
    speed: u8,
}

#[derive(Debug, Deserialize)]
struct Truck {
    load: u16,
    hp: u16,
}

const TEXT: &str = r#"
balls = 5
bricks = 250
[cars]
  [cars.car1]
  color = "green"
  speed = 3
  [cars.car2]
  color = "red"
  speed = 10
[trucks]
  [trucks.truck1]
  load = 15
  hp = 670
  [trucks.truck2]
  load = 25
  hp = 800
"#;

fn main() {
    let toys: Toys = toml::from_str(TEXT).unwrap();
    println!("{:#?}", toys);
}

Thanks a lot! I never really thought of HashMaps, though now that I got the solution delivered on a silver plate it‘s freaking obvious.

Thanks for helping me out :slight_smile:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.