Assuming the following JSON should be read:
let json = r#"{
"scjson": [
{ "StateMachine": { "id": "sm_1" } },
{ "StateMachine": { "id": "sm_2" } }
]
}"#;
In words: An array of StateMachine, with each StateMachine has a field "id" from type string.
How can I deserialize this with serde? I tried:
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct StateMachine {
id: String,
}
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct Scjson {
scjson: Vec<StateMachine>,
}
But the ID is never deserialized.
In the end, I would like to parse:
scjson:
- StateMachine:
id: "sm_1"
states:
- AtomicState:
id: atomic_1
- AtomicState:
id: atomic_2
transitions:
- Transition: { event: "E1", executable_content: "asdf" }
- ParallelState:
InitialTransition: { }
- CompoundState:
id: compound_1
initialTransition: { event: "E2", condition: "some condition" }
- StateMachine:
id: "sm_2"
states:
- FinalState:
id: "asdf"
onEntry: "17"
You are missing one layer of indirection. The scjson
key contains a list of YAML dictionaries, where each dictionary has a single key StateMachine
, and its value is yet another dictionary with one key id
.
Here's the fixed version:
use serde::{Deserialize, Serialize};
use serde_yaml;
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct StateMachine {
id: String,
}
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct Scjson {
scjson: Vec<ScjsonElement>,
}
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct ScjsonElement {
StateMachine: StateMachine,
}
fn main() {
let message = r#"
scjson:
- StateMachine:
id: "sm_1"
- StateMachine:
id: "sm_2"
"#;
let result: Scjson = serde_yaml::from_str(message).unwrap();
println!("{:?}", result)
}
This is the straightforward solution, but it seems that whatever produces the YAML/JSON uses StateMachine
and similar keys to encode the element type. If that is the case, then enum
is the proper answer:
use serde::{Deserialize, Serialize};
use serde_yaml;
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct StateMachine {
id: String,
}
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub struct Scjson {
scjson: Vec<ScjsonElement>,
}
#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
pub enum ScjsonElement {
StateMachine(StateMachine),
}
fn main() {
let message = r#"
scjson:
- StateMachine:
id: "sm_1"
- StateMachine:
id: "sm_2"
"#;
let result: Scjson = serde_yaml::from_str(message).unwrap();
println!("{:?}", result)
}