如何使用Serde选择性地跳过字段的序列化?

11

我有两个结构体:

#[derive(Serialize)]
struct Post {
    title: String,
    // ...more fields...,
    comments: Vec<Comment>,
}

#[derive(Serialize)]
struct Comment {
    body: String,
    // ...more fields...,
}

我想生成两种JSON文件:

  1. 一个Vec<Post>的JSON索引,其中应包括除comments之外的所有字段。
  2. 包括所有字段的Post的JSON。

使用Serialize派生属性是否可以实现这一点?我在Serde的文档中找到了skip_serializing_if属性,但据我所见,它对我没有用,因为我要根据我正在生成的JSON文件跳过而不是基于字段的值。

目前,我正在使用json!宏来生成索引,这需要手动列出Post的所有字段,但我希望有更好的方法来完成这项任务。

1个回答

5
我希望生成两种JSON文件。
我理解为“2种JSON文件类型”,因此我将其作为解决方案。我会创建适合每个上下文的包装类型。这些类型可以引用原始类型,以避免太多的内存开销。
#[derive(Serialize)]
struct LightweightPost<'a> {
    title: &'a String,
}

impl<'a> From<&'a Post> for LightweightPost<'a> {
    fn from(other: &'a Post) -> Self {
        LightweightPost {
            title: &other.title,
        }
    }
}

fn main() {
    let posts = vec![
        Post {
            title: "title".into(),
            comments: vec![Comment { body: "comment".into() }],
        },
    ];

    let listing: Vec<_> = posts.iter().map(LightweightPost::from).collect();

    println!("{}", serde_json::to_string(&listing).unwrap());
    // [{"title":"title"}]

    println!("{}", serde_json::to_string(&posts[0]).unwrap());
    // {"title":"title","comments":[{"body":"comment"}]}
}

游乐场


在编辑方面,我发现使用roar gem在Ruby中编写Web应用程序时,这种多类型结构非常有用。这些新类型允许为特定上下文挂载行为,例如验证或持久性。


谢谢你的回答!我现在可能会坚持使用 json!,因为这比创建一个新的结构体然后实现转换函数更短。 - Dogbert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接