bpi-rs 0.2.0

Bilibili API client library for Rust
Documentation
use serde::{Deserialize, Deserializer, de};

pub(crate) fn deserialize_u64_from_string_or_number<'de, D>(
    deserializer: D,
) -> Result<u64, D::Error>
where
    D: Deserializer<'de>,
{
    let value = serde_json::Value::deserialize(deserializer)?;

    match value {
        serde_json::Value::Number(number) => number
            .as_u64()
            .ok_or_else(|| de::Error::custom("value must be a non-negative integer")),
        serde_json::Value::String(text) => text
            .parse::<u64>()
            .map_err(|_| de::Error::custom("value must be a numeric string")),
        _ => Err(de::Error::custom("value must be a string or number")),
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[derive(Debug, Deserialize)]
    struct Fixture {
        #[serde(deserialize_with = "deserialize_u64_from_string_or_number")]
        value: u64,
    }

    #[test]
    fn deserializes_number() {
        let fixture: Fixture = serde_json::from_str(r#"{ "value": 42 }"#).unwrap();

        assert_eq!(fixture.value, 42);
    }

    #[test]
    fn deserializes_numeric_string() {
        let fixture: Fixture = serde_json::from_str(r#"{ "value": "42" }"#).unwrap();

        assert_eq!(fixture.value, 42);
    }
}