Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(De)serialize remote struct with Option<T> fields #1301

Closed
denizs opened this issue Jun 2, 2018 · 3 comments
Closed

(De)serialize remote struct with Option<T> fields #1301

denizs opened this issue Jun 2, 2018 · 3 comments
Labels

Comments

@denizs
Copy link

denizs commented Jun 2, 2018

Hey there,
I am trying to serialize and deserialize an Option<T> field of a struct I've implemented, where T is a struct implemented in an external crate. Following your documentation, I have implemented a Def struct using the remote macro like so:

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(remote = "ExternalStruct")]
struct ExternalStructDef {
// fields
}

Right now, my struct implementation looks as follows:

#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct MyStruct {
    #[serde(with = "ExternalStructDef")]
    pub value: ExternalStruct,
//...
}

While this works as expected, wrapping ExternalStruct into an Option and using the serde(default) macro throws an error saying expected &external_crate::ExternalStruct.:

#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct MyStruct {
   #[serde(with = "ExternalStructDef")]
  #[serde(default)]
    pub value: Option<ExternalStruct>,
//...
}

Do I have to implement a custom serialize and deserialize method to achieve this?

Best,
Deniz

@dtolnay
Copy link
Member

dtolnay commented Jun 2, 2018

We do not currently support a way to use with = "..." inside of an Option. This is being tracked in #723. For now you would need to write a serialize function and deserialize function yourself.

#[derive(Serialize, Deserialize)]
struct MyStruct {
    #[serde(default, with = "opt_external_struct")]
    value: Option<ExternalStruct>,
}

mod opt_external_struct {
    use super::{ExternalStruct, ExternalStructDef};
    use serde::{Serialize, Serializer, Deserialize, Deserializer};

    pub fn serialize<S>(value: &Option<ExternalStruct>, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        #[derive(Serialize)]
        struct Helper<'a>(#[serde(with = "ExternalStructDef")] &'a ExternalStruct);

        value.as_ref().map(Helper).serialize(serializer)
    }

    pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<ExternalStruct>, D::Error>
    where
        D: Deserializer<'de>,
    {
        #[derive(Deserialize)]
        struct Helper(#[serde(with = "ExternalStructDef")] ExternalStruct);

        let helper = Option::deserialize(deserializer)?;
        Ok(helper.map(|Helper(external)| external))
    }
}

@denizs
Copy link
Author

denizs commented Jun 3, 2018

Awesome, thanks a lot :)
This worked out of the box 👍

@feelingsonice
Copy link

Has this feature been added recently?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

3 participants