如何使用Serde在反序列化期间转换字段?

我正在使用Serde来反序列化具有十六进制值0x400作为字符串的XML文件,我需要将其转换1024u32

我是否需要实现Visitor特征,以便我分离0x,然后将400从基数16解码为基数10?如果是这样,我该如何做才能使基数为10的整数的反序列化保持完整?


侃侃无极
浏览 853回答 3
3回答

慕斯王

该deserialize_with属性最简单的解决方案是使用Serde字段属性 deserialize_with为您的字段设置自定义序列化函数。然后,您可以获取原始字符串并进行适当的转换:use serde::{de::Error, Deserialize, Deserializer}; // 1.0.94use serde_json; // 1.0.40#[derive(Debug, Deserialize)]struct EtheriumTransaction {&nbsp; &nbsp; #[serde(deserialize_with = "from_hex")]&nbsp; &nbsp; account: u64, // hex&nbsp; &nbsp; amount: u64, // decimal}fn from_hex<'de, D>(deserializer: D) -> Result<u64, D::Error>where&nbsp; &nbsp; D: Deserializer<'de>,{&nbsp; &nbsp; let s: &str = Deserialize::deserialize(deserializer)?;&nbsp; &nbsp; // do better hex decoding than this&nbsp; &nbsp; u64::from_str_radix(&s[2..], 16).map_err(D::Error::custom)}fn main() {&nbsp; &nbsp; let raw = r#"{"account": "0xDEADBEEF", "amount": 100}"#;&nbsp; &nbsp; let transaction: EtheriumTransaction =&nbsp; &nbsp; &nbsp; &nbsp; serde_json::from_str(raw).expect("Couldn't derserialize");&nbsp; &nbsp; assert_eq!(transaction.amount, 100);&nbsp; &nbsp; assert_eq!(transaction.account, 0xDEAD_BEEF);}操场请注意,这如何使用任何其他现有的Serde实现进行解码。在这里,我们解码为字符串slice(let s: &str = Deserialize::deserialize(deserializer)?)。您还可以创建直接映射到原始数据的中间结构,派生Deserialize它们,然后在实现中将其反序列化Deserialize。实行 serde::Deserialize从这里开始,这是将其提升为自己的类型以允许重用的一小步:#[derive(Debug, Deserialize)]struct EtheriumTransaction {&nbsp; &nbsp; account: Account, // hex&nbsp; &nbsp; amount: u64,&nbsp; &nbsp; &nbsp; // decimal}#[derive(Debug, PartialEq)]struct Account(u64);impl<'de> Deserialize<'de> for Account {&nbsp; &nbsp; fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>&nbsp; &nbsp; where&nbsp; &nbsp; &nbsp; &nbsp; D: Deserializer<'de>,&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; let s: &str = Deserialize::deserialize(deserializer)?;&nbsp; &nbsp; &nbsp; &nbsp; // do better hex decoding than this&nbsp; &nbsp; &nbsp; &nbsp; u64::from_str_radix(&s[2..], 16)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .map(Account)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .map_err(D::Error::custom)&nbsp; &nbsp; }}操场此方法还允许您添加或删除字段,因为“内部”反序列化类型基本上可以完成所需的操作。
打开App,查看更多内容
随时随地看视频慕课网APP