There is no built-in way until we implement a flatten attribute -- I see you commented on serde-rs/serde#119.
For now you need to deserialize these yourself. Using your data structures from above, something like:
use serde::de::{self, Deserialize, Deserializer};
use serde_json::Value;
impl<'de> Deserialize<'de> for Message {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de>
{
#[derive(Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
enum MessageHelper {
EmotionLevel { message_id: usize },
Car { message_id: usize },
}
let v = Value::deserialize(deserializer)?;
let m = MessageHelper::deserialize(&v).map_err(de::Error::custom)?;
match m {
MessageHelper::EmotionLevel { message_id } => {
Ok(Message::EmotionLevel {
message_id,
emotion: Emotion::deserialize(&v).map_err(de::Error::custom)?,
})
}
MessageHelper::Car { message_id } => {
Ok(Message::Car {
message_id,
part: CarPart::deserialize(&v).map_err(de::Error::custom)?,
})
}
}
}
}