我对于如何优雅且轻松地解析消息感到非常印象serde
深刻serde_json
:
{"msg_type": "asauce", "aaa": 3, "bbb": 14}
{"msg_type": "csyrup", "ccc": 10, "ddd": 20}
// this works!
#[derive(serde::Deserialize, PartialEq, Debug)]
struct AppleSauce {
aaa: u8,
bbb: u8,
}
#[derive(serde::Deserialize, PartialEq, Debug)]
struct ChocolateSyrup {
ccc: u8,
ddd: u8,
}
#[derive(serde::Deserialize, PartialEq, Debug)]
#[serde(tag = "msg_type")]
enum Sauce {
#[serde(rename = "asauce")]
AppleSauce(AppleSauce),
#[serde(rename = "csyrup")]
ChocolateSyrup(ChocolateSyrup),
}
#[test]
fn deserialise_inner_applesauce() {
let json = r#"{"msg_type": "asauce", "aaa": 3, "bbb": 14}"#;
let expected = AppleSauce { aaa: 3, bbb: 14 };
let sauce: Sauce = serde_json::from_str(json).unwrap();
assert_eq!(sauce, Sauce::AppleSauce(expected));
}
但是我的消息有一个父键,我想摆脱它:
{"boilerplate": {"msg_type": "asauce", "aaa": 3, "bbb": 14}}
{"boilerplate": {"msg_type": "csyrup", "ccc": 10, "ddd": 20}}
目前我已经实现了一个from_str
方法:
impl Sauce {
pub fn from_str(msg: &str) -> Option<Sauce> {
let outer: serde_json::Value = serde_json::from_str(msg).ok()?;
let inner = &outer["boilerplate"];
serde_json::from_value(inner.clone()).ok()
}
}
#[test]
fn deserialise_boilerplate_applesauce_with_helper_method() {
let json = r#"{"boilerplate": {"msg_type": "asauce", "aaa": 3, "bbb": 14}}"#;
let expected = AppleSauce { aaa: 3, bbb: 14 };
let sauce = Sauce::from_str(json).unwrap(); // not serde_json::from_str :(
assert_eq!(sauce, Sauce::AppleSauce(expected));
}
有没有办法用 serde 属性来省略父键,并消除自定义from_str
方法?
我只需要反序列化这些消息(但从我看到的 serde 来看,它可能也会免费序列化)。