Search code examples
rustserializationserde

Serde deserialize String into u64


I can't find how to deserialize a JSON string into an integer type using serde. My attempt won't compile:

#[derive(Debug, Deserialize)]
struct WebsocketMessage {
    #[serde(deserialize_with = "str::parse")]
    timestamp: u64
}

Solution

  • Well, str::parse simply doesn't have the right type. The type must be

    fn<'de, D>(D) -> Result<T, D::Error> where D: Deserializer<'de>
    

    as documented here.

    So this function would work:

    fn parse<'de, T, D>(de: D) -> Result<T, D::Error>
    where
        D: serde::Deserializer<'de>,
        T: std::str::FromStr,
        <T as std::str::FromStr>::Err: std::fmt::Display,
    {
        Ok(String::deserialize(de)?
            .parse()
            .map_err(serde::de::Error::custom)?)
    }
    

    Playground

    But really, you'll have an easier time by using the serde_with crate:

    use serde_with::{DisplayFromStr, serde_as};
    
    #[serde_as]
    #[derive(Debug, Deserialize)]
    struct WebsocketMessage {
        #[serde_as(as = "DisplayFromStr")]
        timestamp: u64,
    }
    

    serde_with also has some nice options for parsing timestamps, so you don't even have to use u64.