10

我有两个结构:

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

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

我想生成 2 种 JSON 文件:

  1. a 的 JSON 索引Vec<Post>应包括除comments.
  2. 一个Post包含所有字段的 JSON。

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

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

4

1 回答 1

4

我想生成 2 种 JSON 文件

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

#[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 应用程序时非常有用。这些新类型允许放置特定于某些上下文的行为,例如验证或持久性。

于 2018-01-05T13:55:24.380 回答