Serde_json: cannot treat errors when deserializing String field into i128

Here's the Playground Link.

I cannot properly remove that .unwrap().


I have a JSON body:

{
    "currency": "dolar",
    "quantity": "50"
}

quantity is a String because other languages have problems with large integer primitives (JS), so here's my struct currently:

#[derive(Deserialize)]
pub struct Amount {
    pub currency: String,
    pub quantity: String,
}

However, I wanted to change quantity to be i128:

#[derive(Deserialize)]
pub struct Amount {
    pub currency: String,
    pub quantity: i128,
}

Now I "just" needed to hack the deserialization and convert quantity into i128.

I found this on the internet: Variant attributes · Serde.

#[serde(deserialize_with = "path")]

Where "path" is a path to a function, I can pass a custom deserializer function to that field, so I did it.

#[derive(Deserialize)]
pub struct Amount {
    pub currency: String,
    #[serde(deserialize_with = "deserialize_string_into_i128")]
    pub quantity: i128,
}

// NOTE: `D::Error` is `serde_json::Error` because I'm using `serde_json`.
pub fn deserialize_string_into_i128<'de, D>(deserializer: D) -> Result<i128, D::Error>
where
    D: Deserializer<'de>,
{
    let number = String::deserialize(deserializer)?;
    let number = number.parse::<i128>().unwrap(); // HOW DO I REMOVE THIS UNWRAP?
    Ok(number)
}

I ran into a problem, the String method .parse::<i128>() is fallible.

There is no way to return std::num::ParseIntError, the function returns Result<128, D::Error>.

I can't remove that .unwrap() and treat the error.


Is there other way to do this?

Create a new serde_json::Error from the ParseIntError using .map_err(|e| ...)? .

It's not possible, the function return is enforced to be Result<_, D::Error>, even if it was serde_json::Error, how could I create that from ParseIntError?

serde::de::Error offers Error::custom(impl ToString) -> Self for exactly this; putting custom errors through serde.

For this specific case, you probably just want to use #[serde_as(as = "DisplayFromStr")] (third party adapter crate).

2 Likes

Thanks for the help! It really makes a difference, I was stuck and I can't believe I totally missed that. I'll use it with map_err.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.