serde icon indicating copy to clipboard operation
serde copied to clipboard

Tag enums differently for serialization and deserialization

Open zaghaghi opened this issue 4 months ago • 0 comments

It might be a rare usecase and I have workaround for it, but it would be nice if we could settag container attribute separatly for serialization and deserialization.

To simplify the request, here is a json i would like to deserialize into an enum:

{"struct_type":"A","data":10}

and here is the json that i would like to serialize with the same enum

{"structType":"A","data":10}

and here is my enum definition works only for deserialization:

#[derive(Deserialize, Serialize)]
pub struct A {
    pub data: u8,
}

#[derive(Deserialize)]
#[serde(tag = "struct_type")]
pub enum AB {
    A(A),
}

my workaround is to write a custom serializater, something like this:

impl Serialize for AB {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        #[derive(Serialize)]
        struct EnumTagged<T> {
            #[serde(rename = "structType")]
            struct_type: String,
            #[serde(flatten)]
            base: T,
        }

        match self {
            AB::A(field) => {
                let e = EnumTagged {
                    struct_type: "A".into(),
                    base: field,
                };
                e.serialize(serializer)
            }
        }
    }
}

My suggestion is to have a specific tag for each of serialization and deserialization.

#[derive(Serialize, Deserialize)]
#[serde(tag(serialize= "struct_type", deserialize="structType"))]
pub enum AB {
    A(A),
}

zaghaghi avatar Sep 26 '24 07:09 zaghaghi