serde icon indicating copy to clipboard operation
serde copied to clipboard

Add `#[serde(ref_into = "RefIntoType")]` where `&T: Into<RefIntoType>, RefIntoType: Serialize`

Open timotree3 opened this issue 4 years ago • 2 comments

I suggest adding a container-level attribute ref_into. With this feature, the following two examples would be equivalent:

// Example one

pub struct Foo;

impl Serialize for Foo {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        let val: RefIntoType = self.into();
        val.serialize(serializer)
    }
}
// Example two

#[derive(Serialize)]
#[serde(ref_into = "RefIntoType")]
pub struct Foo;

This feature would be applicable whenever &Foo implements Into<RefIntoType> and RefIntoType implements Serialize.

There's already a very similar shortcut #[serde(into = "IntoType")] but it clones the value before converting and therefore would be wasteful in cases like this where conversion only requires a reference.

As always, the exact chosen name ref_into is subject to bikeshedding.

timotree3 avatar Jun 10 '20 20:06 timotree3

This should be easy to implement, need just introduce and use special RefInto trait, and existing #[serde(into = "IntoType")] should be enough: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=4b5e87587edfb6e35952da321a1d72d9

Mingun avatar Sep 26 '20 08:09 Mingun

I also have a use case for this, but I don't think restricting it to &T: Into or such makes sense. Just having into_with = "path" where path is some fn(&Self) -> T where T: Serialize seems like a more general solution.

JakobDegen avatar Feb 01 '22 05:02 JakobDegen

I think I would prefer to leave this use case to handwritten Serialize impls, instead of introducing new dedicated ref_into or into_with attributes.

As you showed above, these tiny Serialize impls are trivial to handwrite.

dtolnay avatar Jul 09 '23 20:07 dtolnay