如何使用serde_yaml将多个文档序列化到同一个文件?
如何将
Vec<Foo>序列化为多文档YAML文件? 我需要把一个Vec<Foo>序列化为包含多个YAML文档的单个文件,文档之间用---分隔,格式如下:
foo_key: foo_value other_key: 123 other_other_key: [] --- foo_key: bar_value other_key: 312 other_other_key: [other_item] --- foo_key: baz_value other_key: 123321 other_other_key: [item]
我已经能通过以下代码将这类文件反序列化为Vec<Foo>:
#[derive(Debug, Deserialize, Serialize)] struct Foo { foo_key: String, other_key: String, other_other_key: Vec<String>, } let foos: Vec<Foo> = serde_yaml::Deserializer::from_str(&yaml_file) .filter_map(|doc| Foo::deserialize(doc).ok()) .collect();
但不知道怎么反向序列化,而且我不想通过手动拼接每个YAML文档并添加---的方式实现(如下代码),这违背了使用YAML序列化库的初衷:
let serialised_foo_documents = foos .into_iter() .filter_map(|foo| serde_yaml::to_string(&foo).ok()) .reduce(|acc, e| acc + "---\n" + &e) .unwrap_or_default();
解决方案
可以直接使用serde_yaml::Serializer来逐个序列化每个Foo实例,并在文档之间写入分隔符,避免手动拼接字符串:
use serde::{Serialize, Deserialize}; use serde_yaml::{Serializer, SerializerError}; use std::io::Write; #[derive(Debug, Deserialize, Serialize)] struct Foo { foo_key: String, other_key: String, other_other_key: Vec<String>, } // 将Vec<Foo>序列化为多文档YAML的函数 fn serialize_foos<W: Write>(foos: &[Foo], writer: W) -> Result<(), SerializerError> { let mut serializer = Serializer::new(writer); let mut is_first_doc = true; for foo in foos { if !is_first_doc { // 非第一个文档前写入分隔符和换行 serializer.serialize_newline()?; serializer.serialize_str("---")?; serializer.serialize_newline()?; } // 序列化当前Foo实例 foo.serialize(&mut serializer)?; is_first_doc = false; } Ok(()) } // 使用示例 fn main() -> Result<(), Box<dyn std::error::Error>> { let foos = vec![ Foo { foo_key: "foo_value".into(), other_key: "123".into(), other_other_key: vec![], }, Foo { foo_key: "bar_value".into(), other_key: "312".into(), other_other_key: vec!["other_item".into()], }, Foo { foo_key: "baz_value".into(), other_key: "123321".into(), other_other_key: vec!["item".into()], }, ]; // 可以将结果写入文件、内存缓冲区等,这里用Vec<u8>作为示例 let mut buffer = Vec::new(); serialize_foos(&foos, &mut buffer)?; // 输出序列化后的YAML内容 println!("{}", String::from_utf8(buffer)?); Ok(()) }
说明
这个方法直接利用serde_yaml的序列化机制:
- 创建一个
Serializer实例绑定到目标写入器(可以是文件、内存缓冲区等) - 遍历
Vec<Foo>,第一个文档直接序列化,后续文档先写入---分隔符再序列化 - 全程由序列化库处理YAML格式的生成,避免手动拼接字符串可能带来的格式错误
内容的提问来源于stack exchange,提问作者beyarkay
相关产品推荐
相关产品推荐

