У меня есть группа различных сообщений, которые поступают как JSON и могут различаться по одному полю, но тогда каждый вариант имеет свою коллекцию вторичных полей:
#[derive(Debug, Serialize, Deserialize)]
struct MessageOne {
///op will always be "one"
op: String,
x: f64,
y: f64,
}
#[derive(Debug, Serialize, Deserialize)]
struct MessageTwo {
///op will always be "two"
op: String,
a: f64,
b: i64,
}
Различные типы сообщенийнаправляются к различным функциям обработки (например, process_message_one
, process_message_two
и т. д.).Есть ли элегантный или идиоматический способ автоматически выбрать правильный подтип сообщения?В настоящее время я определил общее сообщение:
#[derive(Debug, Serialize, Deserialize)]
struct MessageGeneric {
op: String,
}
, затем проанализировал входящий JSON в MessageGeneric
, прочитал поле op
и затем снова десериализовал, совпав с op
, чтобы выбрать правильное сообщениетип.Полный пример:
#![allow(unused)]
extern crate serde; // 1.0.78
extern crate serde_json; // 1.0.27
#[macro_use]
extern crate serde_derive;
use std::collections::HashMap;
#[derive(Debug, Serialize, Deserialize)]
struct MessageGeneric {
op: String,
}
#[derive(Debug, Serialize, Deserialize)]
struct MessageOne {
///op will always be "one"
op: String,
x: f64,
y: f64,
}
#[derive(Debug, Serialize, Deserialize)]
struct MessageTwo {
///op will always be "two"
op: String,
a: f64,
b: f64,
}
fn process_message_one(m: &MessageOne) {
println!("Processing a MessageOne: {:?}", m);
}
fn process_message_two(m: &MessageTwo) {
println!("Processing a MessageTwo: {:?}", m);
}
fn main() {
let data = r#"{
"op": "one",
"x": 1.0,
"y": 2.0
}"#;
let z: MessageGeneric = serde_json::from_str(data).unwrap();
match z.op.as_ref() {
"one" => {
let zp: MessageOne = serde_json::from_str(data).unwrap();
process_message_one(&zp);
},
"two" => {
let zp: MessageTwo = serde_json::from_str(data).unwrap();
process_message_two(&zp);
},
_ => println!("Unknown Message Type")
}
}
Я видел перечислимые представления Серде , но мне было неясно, будет ли / как это применяться в этом случае.Входящие сообщения определяются внешним API, поэтому я не могу контролировать их содержимое, не зная, какие есть варианты.