#![allow(unused)]
use std::{sync::Arc, collections::HashMap};
use serde::{Deserialize, Deserializer};
use toml::{self, Value}; // 0.5.9
fn main() {
let toml_string = r#"[foobar]
arg = "foo"
[[foobar.skip]]
name = "foo"
attr = [["foo", "bar"], ["baz", "abc"]]
[[foobar.skip]]
name = "another_foo"
"#;
println!("{}",toml_string);
let foo: Custom = toml::from_str(toml_string).unwrap();
println!("Foo: {:?}", foo);
}
#[derive(Debug, Deserialize)]
pub struct Custom {
foobar: FooBar
}
#[derive(Debug, Deserialize)]
pub struct FooBar {
arg: String,
#[serde(deserialize_with = "parse_skip")]
skip: Option<Arc<Vec<Skip>>>,
}
#[derive(Debug, Default)]
pub struct Skip {
pub name: String,
pub attr: Option<Arc<HashMap<String, String>>>,
}
fn parse_skip<'de, D>(deserializer: D) -> Result<Option<Arc<Vec<Skip>>>, D::Error>
where
D: Deserializer<'de>,
{
let mut skips: Vec<Skip> = Vec::new();
let vals: Vec<HashMap<&str, Value>> = Deserialize::deserialize(deserializer)?;
for val in vals.into_iter() {
let mut skip = Skip {
..Default::default()
};
for (k, v) in val.into_iter() {
if k.eq("name") {
skip.name = v.to_string();
}
if k.eq("attr") && v.is_array() {
let labels = v
.as_array()
.into_iter()
.filter(|l| l.len() == 2)
.map(|f| {
(f[0].to_string(), f[1].to_string())
})
.collect::<HashMap<String, String>>();
skip.attr = Some(Arc::new(labels));
}
}
skips.push(skip);
}
Ok(Some(Arc::new(skips)))
}
Output:
[foobar]
arg = "foo"
[[foobar.skip]]
name = "foo"
attr = [["foo", "bar"], ["baz", "abc"]]
[[foobar.skip]]
name = "another_foo"
Foo: Custom { foobar: FooBar { arg: "foo", skip: Some([Skip { name: "\"foo\"", attr: Some({"[\"foo\", \"bar\"]": "[\"baz\", \"abc\"]"}) }, Skip { name: "\"another_foo\"", attr: None }]) } }
Errors:
Compiling playground v0.0.1 (/playground)
Finished dev [unoptimized + debuginfo] target(s) in 1.89s
Running `target/debug/playground`
Is it possible to get rid of the extra double quotes
name: "\"foo\""
and serialize it as
name: "foo"
?
Thank you.