我正在为媒体服务器编写一些文件系统交互。我有一个查询目录内容的功能,有点像ls
命令:
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[derive(Serialize)]
struct File {
name: String,
}
#[derive(Serialize)]
struct Dir {
name: String,
children: Vec<FileOrDir>,
}
#[derive(Serialize)]
enum FileOrDir {
Dir(Dir),
File(File),
}
fn get_some_file_or_dir() -> FileOrDir {
// return some dummy data for this example
FileOrDir::Dir(Dir {
name: "testdir".to_string(),
children: vec![
FileOrDir::File(File {
name: "testfile".to_string(),
}),
FileOrDir::Dir(Dir {
name: "nesteddir".to_string(),
children: vec![],
}),
],
})
}
我可以像这样调用+序列化:
fn main() {
println!(
"{}",
serde_json::to_string(&get_some_file_or_dir()).unwrap()
);
}
但是,我不喜欢将enum FileOrDir
作为求和类型。同样,enum
类型的serde中的默认序列化使输出到处都有“ Dir”和“ File”的混乱。是否有更好的方法来为类似的事情做求和类型?这是impl / trait用于什么目的?我试图实现它,但是它非常冗长。我想说的基本上是这样的:
fn get_some_file_or_dir() -> File | Dir
或者,我可以编写一个自定义的序列化程序来摆脱JSON序列化中的“文件”和“目录”节点,而是在静态"type": "f"
或"type": "d"
上进行标记吗?我也尝试过,但是它变得非常静态。我真的必须像下面那样“重新序列化”整个结构吗?如果结构发生了变化,那么即使serde应该已经知道如何进行序列化,我也必须更新该自定义序列化:
impl Serialize for FileOrDir {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
FileOrDir::File(f) => {
let mut state = serializer.serialize_struct("File", 2)?;
state.serialize_field("name", &f.name)?;
state.serialize_field("type", "f")?;
state.end()
}
FileOrDir::Dir(d) => {
let mut state = serializer.serialize_struct("Dir", 3)?;
state.serialize_field("path", &d.name)?;
state.serialize_field("children", &d.children)?;
state.serialize_field("type", "d")?;
state.end()
}
}
}
}