Estou realmente impressionado com a elegância e facilidade com que serde
consigo serde_json
analisar mensagens:
{"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));
}
Entretanto, minhas mensagens têm uma chave pai, da qual gostaria de me livrar:
{"boilerplate": {"msg_type": "asauce", "aaa": 3, "bbb": 14}}
{"boilerplate": {"msg_type": "csyrup", "ccc": 10, "ddd": 20}}
No momento implementei um from_str
método:
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));
}
Existe uma maneira de eliminar a chave pai com um atributo serde e eliminar o from_str
método personalizado?
Só preciso desserializar essas mensagens (mas pelo que vejo no serde, ele provavelmente seria serializado também de graça).