Json: Is there a way to parse a number from string?

Created on 15 Feb 2018  路  6Comments  路  Source: serde-rs/json

Let's say we have an example:

{
    "user": {
        "id": "78358783457112"
    }
}

Is there a way to parse it into this:

#[derive(Deserialize)]
struct UserId(pub u64)

#[derive(Deserialize)]
struct User {
    user_id: UserId
}

At this moment it works perfectly and does not parse this because of types: the u64 type is expected rather than String. However, I'd like to have an option to parse numbers from string too. What about doing it like this?

#[derive(Deserialize)]
struct User {
    #[serde(from_string)]
    user_id: UserId
}

I was unable to find something like this in the documentation, if there is such an option, feel free to point me right there.

support

Most helpful comment

I made some very easy library because I needed this functionality very much. I think I will elaborate it later.

All 6 comments

You could provide a Deserialize impl for UserId that handles integers and strings -- playground. Or if you want to handle strings only in this one place and not change the Deserialize impl, you would do that with a deserialize_with attribute on the user_id field. That attribute specifies an alternative way to deserialize a field other than the Deserialize impl of the field's type. This page gives an example of using deserialize_with.

@dtolnay thanks, I thought about that too. But would not it be simpler for users just to have this as a macro attribute as I proposed above? This is a common problem with javascript, for example, where it does not have big integer numbers but floats only so services provide strings instead of numbers.

Yes you're right! I missed the suggestion. We have been tracking this in https://github.com/serde-rs/serde/issues/553#issuecomment-297391825 along with some other recurring customizations that would be valuable to provide in an auxiliary library. Would you be interested in picking some of the use cases from that thread and designing a library around them to provide implementations as serialize_with / deserialize_with functions?

@dtolnay I'd try doing that, just depends on my free time. Now, it seems, I don't have any other choice, because my code really needs to parse string numbers and I want to do it gracefully :) So, this library obviously will not be able to use serde attributes because they are owned by another crate which the auxiliary library will depend on. Could you suggest me a name for such an attribute? Or, another way, the auxiliary library could just provide a module with implementations which could be used with:

#[derive(Deserialize)]
struct A {
    [serde(with = "my_auxiliary_library::string_to_int")]
    value: u64
}

Update: Ok, I think it is reasonable to provide both if possible: serde_aux attribute and the module because it will be needed anyway.

I made some very easy library because I needed this functionality very much. I think I will elaborate it later.

Any official updates here?

Was this page helpful?
0 / 5 - 0 ratings