EDIT: I had forgotten about serde::Deserialize::deserialize_in_place (hidden in documentation) when I wrote this answer. While this answer does show how similar results can be achieved with a Visitor, I recommend following kmdreko's answer instead.
We can't fully deserialize everything in place because serde is designed around returning the value as we deserialize it. However, it you just want to deserialize into a single Vec, we can make a visitor to handle that situation. Here is roughly what that would look like.
use serde::de::{DeserializeOwned, SeqAccess, Visitor}; use serde::{Deserialize, Deserializer}; use std::fmt::{self, Formatter}; struct InPlaceVisitor<'a, T> { buffer: &'a mut Vec<T>, } impl<'de, 'a: 'de, T> Visitor<'de> for InPlaceVisitor<'a, T> where T: Deserialize<'de>, { /// We are deserializing in place so we won't have any output type Value = (); /// Every visitor needs to implement this function to add some /// context to error messages. This will be called if any of the /// `visit_*` functions we didn't implement get called. fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "sequence of values") } /// Handle the case where the deserializer finds a sequence of /// values. fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> where A: SeqAccess<'de>, { // Clear the buffer before we begin self.buffer.clear(); // If the deserializer knows the number of items in the // sequence we can ensure we have enough capacity before // starting. However, this is generally only the case for // formats that prefix sequences with their lengths. if let Some(hint) = seq.size_hint() { self.buffer.reserve(hint); } // Now we can just read the values and add them to the // buffer. This will call serde::Deserialize::deserialize for // each element. while let Some(value) = seq.next_element()? { self.buffer.push(value); } Ok(()) } }
Now, one of the tricky parts of using this is that we need to construct our visitor with the buffer we want to push to. This is tricky that means we will not have access to our buffer within serde::Deserialize::deserialize. As a result, we must construct the deserializer ourselves. Not all serde formats expose their Serializer and Deserializer types so this solution won't be possible for all data formats. Luckily serde_json does expose its deserializer, so we can implement a general function to use our visitor.
pub fn deserialize_json_in_place<'de, 'a: 'de, T, R>( reader: R, buffer: &'a mut Vec<T>, ) -> serde_json::Result<()> where T: Deserialize<'de>, R: serde_json::de::Read<'de>, { let mut deserializer = serde_json::de::Deserializer::new(reader); let visitor = InPlaceVisitor { buffer }; // We tell the deserializer what we are hoping to find, then the // deserializer calls the `visit_*` function corresponding to the // type it actually encountered. deserializer.deserialize_seq(visitor) }
With this, we are all set. However for convenience, you may still want to make some simple wrapper functions to handle creating the reader.
pub fn from_str_into<T>(x: &str, buffer: &mut Vec<T>) -> serde_json::Result<()> where T: DeserializeOwned, { let reader = serde_json::de::StrRead::new(x); deserialize_json_in_place(reader, buffer) }
Rust Playground