【问题标题】:Optionally skip serializing a field with Serde?可以选择跳过使用 Serde 序列化字段?
【发布时间】:2018-01-05 06:38:51
【问题描述】:

我有两个结构:

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

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

我要生成2种JSON文件:

  1. Vec&lt;Post&gt; 的 JSON 索引应包括除 comments 之外的所有字段。
  2. Post 的 JSON,包含所有字段。

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

现在我正在使用json! 宏生成索引,这需要手动列出Post 的所有字段,但我希望有更好的方法来做到这一点。

【问题讨论】:

    标签: rust serde


    【解决方案1】:

    我要生成2种JSON文件

    我将其解读为“JSON 文件的 2 个 类型”,因此我将其作为解决方案。我会创建适合每个上下文的包装器类型。这些可以引用原始类型以避免过多的内存开销:

    #[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"}]}
    }
    

    playground


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

    【讨论】:

    • 感谢您的回答!我现在可能会坚持使用json!,因为这比创建新结构然后实现转换函数要短。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 2018-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-16
    相关资源
    最近更新 更多