La solution la plus simple consiste à utiliser le Serde field attributedeserialize_with
pour définir une fonction de sérialisation personnalisée pour votre champ. Vous pouvez ensuite obtenir la chaîne brute et convert it as appropriate:
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
use serde::{Deserialize, Deserializer};
use serde::de::Error;
#[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);
}
playground
De là, il est un petit pas à la promotion à votre propre type pour permettre sa réutilisation:
#[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)
}
}
playground
Voir aussi:
Merci @Shepmaster. C'est exactement ce que je cherche. Le seul problème est la référence à la chaîne que je reçois cette panique msg: type non valide: chaîne « 0x400 », attend une chaîne empruntée. – phodina
@phodina Mes deux exemples exécuter avec succès, si évidemment vous avez changé quelque chose. Je ne suis pas un lecteur d'esprit, donc je ne sais pas quelle est cette différence. Vous pouvez essayer 'let s: String = ...' dans le cas où le décodeur XML ne peut pas fournir de tranches de chaîne. – Shepmaster
J'ai essayé vos deux exemples dans le terrain de jeu et sur mon PC et ils fonctionnent tous les deux. Le problème survient lorsque je change le format sous-jacent de json en xml. Voici le code (terrain de jeu manque la caisse serde_xml_rs) let raw = r # " 0xDEADBEEF EtheriumTransaction>" #; transaction let. EtheriumTransaction = serde_xml_rs :: deserialize (raw.as_bytes()) déroulez(); –
phodina