I’m new to Rust and have a project that requires specifying a config that is a tree. In JSON this would be like:
{
"a": {
"d": {
"val": 10
},
"e": {
val: 20
}
},
"b": {
"val": 5
},
"c": {
"val": 1
}
}
Here the root has 3 children "a,b,c" and "a" has two children "d,e" with one associated with the value 10 and another with the value 20 etc. In other words, the tree can have arbitrary depth and only leaf nodes have values associated.
My question: Is there a way to parse such a structure in Rust strait into some structs? What would be the cleanest way to parse something like this?
>Solution :
What would be the cleanest way to parse something like this?
That is dependent on your use-case, I’d say. I think the simplest solution would be to parse this into an untagged enum with either a leaf with a value, or a subtree. For the subtree a HashMap can be used. Here a simple example that can parse your json:
use std::collections::HashMap;
use serde::Deserialize;
#[derive(Deserialize, PartialEq, Debug)]
#[serde(untagged)]
enum Node {
Leaf { val: u8 },
Tree(HashMap<String, Node>),
}
fn main() {
let json = r#"{
"a": {
"d": {
"val": 10
},
"e": {
"val": 20
}
},
"b": {
"val": 5
},
"c": {
"val": 1
}
}"#;
let tree: Node = serde_json::from_str(json).unwrap();
let expect = Node::Tree(HashMap::from([
(
"a".to_owned(),
Node::Tree(HashMap::from([
("d".to_owned(), Node::Leaf { val: 10 }),
("e".to_owned(), Node::Leaf { val: 20 }),
])),
),
("b".to_owned(), Node::Leaf { val: 5 }),
("c".to_owned(), Node::Leaf { val: 1 }),
]));
assert_eq!(tree, expect);
}
But like I said, it depends what you want to do with the tree in your Rust code, whether this data structure is feasible for you or not.