I'm writing a program in rust and I would prefer use a TOML file to store a vector of struct
's. However I can't figure out how to store a vector of struct
's in a TOML file. I am able to do this using JSON but was hoping for TOML so just confirming that I'm not overlooking something (not even sure if the TOML format would be able to support what I want). Therefore, I'm trying to find out if anyone knows of a way use rust to serialize a vector of struct
's to TOML and more importantly to deserialize it back into a vector.
thread 'main' panicked at 'called Result::unwrap()
on an Err
value: Error { inner: ErrorInner { kind: Wanted { expected: "a table key", found: "a right bracket" }, line: Some(0), col: 2, at: Some(2), message: "", key: [] } }', src/main.rs:22:55
note: run with RUST_BACKTRACE=1
environment variable to display a backtrace
Cargo.toml
[dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1.0.86"
toml = "0.5.9"
Link to code on Playground
use serde::{Deserialize, Serialize};
#[derive(PartialEq, Debug, Serialize, Deserialize)]
struct Point {
x: i32,
}
/// An ordered list of points (This is what I want to store in the TOML file)
type Points = Vec<Point>;
fn main(){
// Create sample data to test on
let original: Points = vec![Point { x: 1 }];
// Working code that converts it to json and back
let json = serde_json::to_string(&original).unwrap();
let reconstructed: Points = serde_json::from_str(&json).unwrap();
assert_eq!(original, reconstructed); // No panic
// "Desired" code that converts it to toml but unable to deserialize
let toml = toml::to_string(&original).unwrap();
let reconstructed: Points = toml::from_str(&toml).unwrap(); // Panics!
assert_eq!(original, reconstructed);
}
toml::to_string(&original).unwrap()
[[]]
x = 1
In the example code I create some sample data then convert it to JSON and back with no issue. I then try to convert it to TOML, which doesn't give an error but the output doesn't make sense to me. Then I try to convert it back into a rust vector and that triggers the error. My biggest problem is I'm not even sure how I would expect the TOML file to look for a valid representation of a vector with multiple struct
's.
I wasn't able to find any information for creating a vector with multiple struct
's the closest I could find is this question, and while the question looks like it should solve my problem the actual problem was serializing enums and the solution hence refers to that and doesn't solve my problem.
It seems that to represent an array of tables in Toml the syntax is
[[points]]
x = 1
[[points]]
x = 2
So backtracking from Toml syntax and original panic error Error { inner: ErrorInner { kind: Wanted { expected: "a table key", found: "a right bracket" }
: Introducing a wrapper struct to represent table key fixes the issue.
use serde::{Deserialize, Serialize};
#[derive(PartialEq, Debug, Serialize, Deserialize)]
struct Point {
x: i32,
}
#[derive(PartialEq, Debug,Serialize, Deserialize)]
struct Points {
points: Vec<Point>
}
impl From<Vec<Point>> for Points {
fn from(points: Vec<Point>) -> Self {
Points {
points
}
}
}
fn main(){
let original: Points = vec![Point { x: 1 }, Point {x : 2}].into();
let json = serde_json::to_string(&original).unwrap();
let reconstructed: Points = serde_json::from_str(&json).unwrap();
assert_eq!(original, reconstructed);
let toml = toml::to_string(&original).unwrap();
let reconstructed: Points = toml::from_str(&toml).unwrap();
assert_eq!(original, reconstructed);
}