将一个字段反序列化为2个字段

问题描述 投票:0回答:1

我正在尝试将字段“名称”反序列化为“名字”和“姓氏”。

我的结构:

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`") }

我的问题:如何将一个字段反序列化为两个不同的字段?

rust serialization deserialization
1个回答
0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.