如何将JSON数组反序列化至已创建的Rust Vec以实现复用?
将JSON反序列化至现有Vec的解决方案
serde_json没有直接提供from_str_into这类直接写入现有Vec的API,但可以通过以下两种方式实现内存复用:
方案一:自定义Visitor实现
通过实现serde的Visitor trait,持有目标Vec的可变引用,在反序列化数组时直接将元素写入已有Vec:
use serde::{de::Visitor, Deserialize, Deserializer}; use serde_json; use std::fmt; fn request(i: usize) -> String { let mut v = vec![0; i]; for n in 1..i { v[n] = n as i32; } serde_json::to_string(&v).unwrap() } struct VecVisitor<'a, T: Deserialize<'a>> { target: &'a mut Vec<T>, } impl<'a, T: Deserialize<'a>> Visitor<'a> for VecVisitor<'a, T> { type Value = (); fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a JSON array") } fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> where A: serde::de::SeqAccess<'a>, { self.target.clear(); // 预分配容量优化性能(可选) if let Some(len) = seq.size_hint() { self.target.reserve(len); } while let Some(element) = seq.next_element()? { self.target.push(element); } Ok(()) } } fn deserialize_into_vec<'a, T: Deserialize<'a>>(json: &'a str, target: &mut Vec<T>) -> Result<(), serde_json::Error> { let deserializer = serde_json::Deserializer::from_str(json); let visitor = VecVisitor { target }; deserializer.deserialize_seq(visitor) } fn main() { let mut bigvec = serde_json::from_str::<Vec<i32>>(&request(100)).unwrap(); println!("{:?}", &bigvec); let many_iterations = 10; for n in 1..many_iterations { let resp = request(n); deserialize_into_vec(&resp, &mut bigvec).unwrap(); println!("Iteration {}: len = {}", n, bigvec.len()); } }
方案二:流式反序列化简化实现
利用serde_json的StreamDeserializer逐个解析数组元素,直接写入现有Vec,无需自定义Visitor:
use serde_json::{self, Deserializer}; use serde::Deserialize; fn request(i: usize) -> String { let mut v = vec![0; i]; for n in 1..i { v[n] = n as i32; } serde_json::to_string(&v).unwrap() } fn deserialize_into_vec<T: for<'a> Deserialize<'a>>(json: &str, target: &mut Vec<T>) -> Result<(), serde_json::Error> { target.clear(); let deserializer = Deserializer::from_str(json); let mut stream = deserializer.into_iter::<T>(); while let Some(item) = stream.next() { target.push(item?); } Ok(()) } fn main() { let mut bigvec = serde_json::from_str::<Vec<i32>>(&request(100)).unwrap(); println!("{:?}", &bigvec); let many_iterations = 10; for n in 1..many_iterations { let resp = request(n); deserialize_into_vec(&resp, &mut bigvec).unwrap(); println!("Iteration {}: len = {}", n, bigvec.len()); } }
核心要点
- 两种方案都会先调用
target.clear()清空Vec,再写入新元素,完全复用原有内存空间。 - 方案一中的
reserve(len)可选,用于根据序列预估长度预分配内存,减少动态扩容开销。 - 方案二代码更简洁,无需手动实现Visitor,适合大多数常规场景。
内容的提问来源于stack exchange,提问作者fvall
相关产品推荐
相关产品推荐

