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)
}
}
操場
此方法還允許您添加或刪除字段,因為“內部”反序列化類型基本上可以完成所需的操作。
添加回答
舉報