我正在尝试将字段“名称”反序列化为“名字”和“姓氏”。
我的结构:
struct User {
#[serde(rename = "name", deserialize_with = "deserialize_firstname")]
firstname: String,
#[serde(deserialize_with = "deserialize_lastname")]
#[serde(rename = "name")]
lastname: String,
}
反序列化函数如下:
fn deserialize_firstname<'de, D>(deserializer: D) -> Result<String, D::Error>
where
D: serde::Deserializer<'de>,
{
let s: &str = serde::Deserialize::deserialize(deserializer)?;
let re = Regex::new(r"^\W*([\w-]+)").unwrap();
let m = re.find(s);
match m {
Some(value) => Ok( value.as_str().to_string()),
None => Ok("".to_string()),
}
}
(姓氏也差不多)。
我收到以下错误:
err: DeserializeError { field: None, kind: Message("missing field `name`") }
我的问题:如何将一个字段反序列化为两个不同的字段?
Serde 可以展平结构,使 Rust 表示比序列化表示更加嵌套,但它不能展平,而您在这里尝试这样做。相反,您可以通过注释整个结构来自己完成此操作。这里我们有反映序列化结构的
UserSerde
,并将其转换为 User
,这就是您要寻找的。 (游乐场)
#[derive(Debug, Deserialize)]
struct UserSerde {
name: Name,
}
#[derive(Debug, Deserialize)]
#[serde(try_from = "&str")]
struct Name {
first: String,
last: String,
}
impl<'a> TryFrom<&'a str> for Name {
type Error = &'static str;
fn try_from(value: &'a str) -> Result<Self, Self::Error> {
let re = regex::Regex::new(r"^\W*([\w-]+)\W+([\w-]+)\W*$").unwrap();
let Some(caps) = re.captures(value) else {
return Err("could not parse a first and last name");
};
Ok(Self {
first: caps[1].to_string(),
last: caps[2].to_string(),
})
}
}
#[derive(Debug, Deserialize)]
#[serde(from = "UserSerde")]
struct User {
first: String,
last: String,
// other fields...
}
impl From<UserSerde> for User {
fn from(value: UserSerde) -> Self {
let UserSerde {
name: Name { first, last },
} = value;
Self { first, last }
}
}
请注意,如果您使用它来存储任意人名,那么将它们分成名字和姓氏不是一个好主意。至少有一个正常的后备措施
String
。