Fabus1184
Fabus1184

Reputation: 149

Rust serde remote derive trait bounds were not satisfied

#[derive(serde::Serialize, serde::Deserialize)]
#[serde(remote = "ExternalType")]
pub struct ExternalTypeWrapper {
   ...
}

#[derive(serde::Serialize, serde::Deserialize)]
struct X {
    // works
    #[serde(with = "ExternalTypeWrapper")]
    x1: ExternalType,

    // does not work
    #[serde(with = "Vec::<ExternalTypeWrapper>")]
    x2: Vec<ExternalType>,
}

Why does my remote derived (De)Serialize only work for the plain type, but not if it is wrapped in something like a Vec? This gives the following error:

the function or associated item `serialize` exists for struct `Vec<ExternalTypeWrapper>`, but its trait bounds were not satisfied
the following trait bounds were not satisfied:
`ExternalTypeWrapper: Serialize`
which is required by `Vec<ExternalTypeWrapper>: Serialize`
`Vec<ExternalTypeWrapper>: Serialize`
which is required by `&Vec<ExternalTypeWrapper>: Serialize`
`Vec<ExternalTypeWrapper>: Serialize`
which is required by `&mut Vec<ExternalTypeWrapper>: Serialize`

(analogous for the Deserialize trait)

Upvotes: 0

Views: 163

Answers (1)

jonasbb
jonasbb

Reputation: 2583

This is not possible with only serde. There is an old bug report about it, but no solutions from the serde maintainers. You can use serde_with to solve it. The steps are explained in the user guide.

Using the two traits SerializeAs/DeserializeAs, which work similar to the serde ones, you can add support for nesting types, like Option or Vec. You then annotate the struct and field with serde_as instead of using serde(with = "...").

/*
[dependencies]
serde = "1"
serde_with = "3"
*/

pub struct ExternalType {
    foo: (),
}

fn main() {
    #[derive(serde::Serialize, serde::Deserialize)]
    #[serde(remote = "ExternalType")]
    pub struct ExternalTypeWrapper {
        foo: (),
    }

    // https://docs.rs/serde_with/latest/serde_with/guide/serde_as/index.html#using-serde_as-with-serdes-remote-derives
    impl serde_with::SerializeAs<ExternalType> for ExternalTypeWrapper {
        fn serialize_as<S>(value: &ExternalType, serializer: S) -> Result<S::Ok, S::Error>
        where
            S: serde::Serializer,
        {
            ExternalTypeWrapper::serialize(value, serializer)
        }
    }

    impl<'de> serde_with::DeserializeAs<'de, ExternalType> for ExternalTypeWrapper {
        fn deserialize_as<D>(deserializer: D) -> Result<ExternalType, D::Error>
        where
            D: serde::Deserializer<'de>,
        {
            ExternalTypeWrapper::deserialize(deserializer)
        }
    }

    #[serde_with::serde_as]
    #[derive(serde::Serialize, serde::Deserialize)]
    struct X {
        // works
        #[serde(with = "ExternalTypeWrapper")]
        x1: ExternalType,

        // does not work
        #[serde_as(as = "Vec<ExternalTypeWrapper>")]
        x2: Vec<ExternalType>,
    }
}

Solution on Rustexplorer

Upvotes: 1

Related Questions