- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一组不同的消息,它们以 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")
}
}
我看过 Serde's enum representations但我不清楚在这种情况下是否/如何应用。传入的消息由外部 API 定义,因此除了知道变体是什么之外,我无法控制它们的内容。
最佳答案
在你的结构 MessageOne
和 MessageTwo
中保留“一”或“二”是没有意义的:如果你已经构造了这个结构,你就已经知道它是否是消息一或消息二。
extern crate serde; // 1.0.78
extern crate serde_json; // 1.0.27
#[macro_use]
extern crate serde_derive;
#[derive(Serialize, Deserialize, Debug)]
#[serde(tag = "op")]
enum Message {
#[serde(rename = "one")]
One { x: f64, y: f64 },
#[serde(rename = "two")]
Two { a: f64, b: f64 },
}
fn process_message(message: &Message) {
println!("Processing a : {:?}", message);
}
use serde_json::Error;
fn main() -> Result<(), Error> {
let data = r#"{
"op": "one",
"x": 1.0,
"y": 2.0
}"#;
let message: Message = serde_json::from_str(data)?;
process_message(&message);
let data = r#"{
"op": "two",
"a": 1.0,
"b": 2.0
}"#;
let message: Message = serde_json::from_str(data)?;
process_message(&message);
let data = r#"{
"op": "42",
"i": 1.0,
"j": 2.0
}"#;
let message: Message = serde_json::from_str(data)?;
process_message(&message);
Ok(())
}
Standard Output
Processing a : One { x: 1.0, y: 2.0 }
Processing a : Two { a: 1.0, b: 2.0 }
Standard Error
Error: Error("unknown variant `42`, expected `one` or `two`", line: 2, column: 18)
关于rust - Serde 能否根据字段的值将 JSON 反序列化为一组类型中的一种?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53018165/
我有一个使用the #[serde(default)] container attribute的结构。 但是,应该有一个字段是必需的(如果输入数据中不存在该字段,则反序列化器应该出错,而不是退回到默认
我正在尝试使用 actix-web 服务器作为通往小型堆栈的网关,以保证堆栈内部的数据格式严格,同时为用户提供一些自由。 为此,我想将 JSON 字符串反序列化为结构,然后对其进行验证、再次序列化并将
正在使用 apache-hive-0.13.1。在创建表配置单元时抛出如下错误 FAILED: Execution Error, return code 1 from org.apache.hadoo
我想添加一个简单的版本方案 + 检查我的结构: #[derive(Serialize, Deserialize)] struct Versioned { version: u32, o
我正在尝试使用 Serde 加载一个 Toml 文件,它包含多个 bool 值,如果在文本文件中找不到,我想将它们全部默认为 false。 我目前的实现是: #[derive(serde::Deser
如何使用 Serde 为远程类型创建序列化程序代理对象?这是一个最小的例子(playground): use serde; // 1.0.104 use serde_json; // 1.0.48 s
我有一个枚举: #[derive(Serialize, Deserialize)] enum Action { Join, Leave, } 和一个结构: #[derive(Seria
我有一个枚举: #[derive(Serialize, Deserialize)] enum Action { Join, Leave, } 和一个结构: #[derive(Seria
在 Rust 中,我从 websocket 接收数据。为简单起见,它看起来像这样: [1, {"a": ["1.2345", 5, "9.8765"]}] 我从 websocket 获得的字符串确实
我的程序解析足够大的 json 文档(30MB),在 CPU 较慢的机器上需要 70 毫秒,我想加快这个过程,我发现 27% 的解析发生在我的 foo_document_type_deserializ
我正在尝试在配置单元中创建一个正则表达式 serde 来读取一些日志文件,但是在让它工作时遇到了问题... 日志文件看起来像这样...... 14.196.202.16:9123 11329 2
我正在使用映射列的 JSON-Serde 功能来重命名我的 json 文档中的列 'Customer ID' -> 'customer_id。我使用映射函数的原因是因为 HQL 不允许在 CREATE
我有一个包含 Text 键和 DoubleWritable 值的序列文件。当我将文件加载为外部表时 Create external table t (id String, data Double) S
假设我有这个结构: use serde::{Serialize, Deserialize}; #[derive(Deserialize)] struct MyStruct { field_1:
这段代码完全按照我的意愿序列化了一个 32 字节的数组: #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOr
我正在使用 event_emmiter_rs用于我的应用程序中的事件处理。该库允许您订阅带有回调的事件并触发这些事件。事件采用 (strings, value) 的形式,回调采用接受值参数的闭包形式。
给定这个枚举定义: #[repr(u8)] #[derive(Debug, Serialize)] pub enum AnimalType { #[serde(rename = "cat")]
我目前正在使用 Rocket 开发一个 Web API,它使用以下结构进行错误响应: #[derive(Serialize, Deserialize)] pub struct ErrorRespons
我想解析这个日志样本 May 3 11:52:54 cdh-dn03 init: tty (/dev/tty6) main process (1208) killed by TERM signal M
我想从访问日志中提取(ip、requestUrl、timeStamp)以加载到 hive 数据库。访问日志中的一行如下。 66.249.68.6 - - [14/Jan/2012:06:25:03 -
我是一名优秀的程序员,十分优秀!