为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

侃侃无极 2019-10-22 21:38:25
我正在使用Serde来反序列化具有十六进制值0x400作为字符串的XML文件,我需要将其转换1024为u32。我是否需要实现Visitor特征,以便我分离0x,然后将400从基数16解码为基数10?如果是这样,我该如何做才能使基数为10的整数的反序列化保持完整?
查看完整描述

3 回答

?
慕斯王

TA贡献1864条经验 获得超2个赞

该deserialize_with属性

最简单的解决方案是使用Serde字段属性 deserialize_with为您的字段设置自定义序列化函数。然后,您可以获取原始字符串并进行适当的转换:


use serde::{de::Error, Deserialize, Deserializer}; // 1.0.94

use serde_json; // 1.0.40


#[derive(Debug, Deserialize)]

struct EtheriumTransaction {

    #[serde(deserialize_with = "from_hex")]

    account: u64, // hex

    amount: u64, // decimal

}


fn from_hex<'de, D>(deserializer: D) -> Result<u64, D::Error>

where

    D: Deserializer<'de>,

{

    let s: &str = Deserialize::deserialize(deserializer)?;

    // do better hex decoding than this

    u64::from_str_radix(&s[2..], 16).map_err(D::Error::custom)

}


fn main() {

    let raw = r#"{"account": "0xDEADBEEF", "amount": 100}"#;

    let transaction: EtheriumTransaction =

        serde_json::from_str(raw).expect("Couldn't derserialize");

    assert_eq!(transaction.amount, 100);

    assert_eq!(transaction.account, 0xDEAD_BEEF);

}

操场


请注意,这如何使用任何其他现有的Serde实现进行解码。在这里,我们解码为字符串slice(let s: &str = Deserialize::deserialize(deserializer)?)。您还可以创建直接映射到原始数据的中间结构,派生Deserialize它们,然后在实现中将其反序列化Deserialize。


实行 serde::Deserialize

从这里开始,这是将其提升为自己的类型以允许重用的一小步:


#[derive(Debug, Deserialize)]

struct EtheriumTransaction {

    account: Account, // hex

    amount: u64,      // decimal

}


#[derive(Debug, PartialEq)]

struct Account(u64);


impl<'de> Deserialize<'de> for Account {

    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>

    where

        D: Deserializer<'de>,

    {

        let s: &str = Deserialize::deserialize(deserializer)?;

        // do better hex decoding than this

        u64::from_str_radix(&s[2..], 16)

            .map(Account)

            .map_err(D::Error::custom)

    }

}

操场


此方法还允许您添加或删除字段,因为“内部”反序列化类型基本上可以完成所需的操作。


查看完整回答
反对 回复 2019-10-22
  • 3 回答
  • 0 关注
  • 851 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信