(De)serialize delimited string to/from Vec

I have some structs with fields of Vec<T> where T is a String or enum that derives (De)Serailize. These structs are converted to/from query strings, e.g. ?field=value. The value of the field should be pipe delimited, e.g. foo|bar|baz.

I'm using warp which helpfully deserializes the query strings to structs, so I'm currently adding serialize_with and deserialize_with attributes to the struct fields that get this extra behaviour. I've come across implementations that use the Display and FromStr traits to achieve this to some extent serde_with::rust::StringWithSeparator - Rust. What I'd like to be able to do is split a string and defer to the enum's deserializer to do the rest (if it's an enum) and serialize an enum to string and join them together.

I've had a rough stab at this in Rust Playground but I'm not getting very far. Would anyone be able to suggest what I should do next?

Is there anything missing from StringWithSeparator which makes it unusable for your situation?

In your playground you are serializing the data as a sequence. This does not allow you to put the | delimiters in it. Only the Serializer has control over the final output (and thus the separator characters). You could use or write a Serializer which does that.

The way StringWithSeparator works around that is to do the string building itself and hand the Serializer a fully formatted string. It iterates over the collection, calls to_string on all elements, joins them with the separator, and then does a single serialize_str call.

If StringWithSeparator is close enough to your needs, I would simply copy the implementation and change the Display/FromStr parts with the serializer you have in mind.

If StringWithSeparator is close enough to your needs, I would simply copy the implementation and change the Display/FromStr parts with the serializer you have in mind.

It's super close to what I need, I just can't quite figure out how to replace display/from_str with (de)serialize.

You need to replace these two lines with your (de-)serialize code:

// Serialize
s.push_str(&*v.to_string());

// Deserialize
.map(FromStr::from_str)

As trait bounds you probably want

// Serialize
V: Serialize,

// Deserialize
V: DeserializeOwned,

Thanks! I found serde_plain which handles the conversion just how I wanted. Combined with lifting code from serde_with, I ended up with this Rust Playground