如何在序列化空值或默认值时避免生成JSON?

37
serde_json::to_string() 函数生成的字符串可能包括 null(对于 Option<T>)或 0(对于 u32)等这些值。这会使输出变大,因此我想忽略这些值。
我希望简化以下结构的 JSON 字符串输出:
use serde_derive::Serialize; // 1.0.82

#[derive(Serialize)]
pub struct WeightWithOptionGroup {
    pub group: Option<String>,
    pub proportion: u32,
}
当`group`为`None`且`proportion`为0时,JSON字符串应为`"{}"`。感谢您回答了如何将Serde的默认实现更改为返回空对象而不是null?问题,它可以解决`Option`的问题,但对于`0`没有解决方案。

1
重复的问题:如何更改Serde的默认实现以返回空对象而不是null? - Shepmaster
4
可能是重复的问题,与“如何更改Serde的默认实现以返回空对象而不是null?”相似。 - Stargateur
它可以解决“Option”问题,但对于0没有解决方案。 - llxxbb
3个回答

72

跳过序列化字段的链接给了我答案。

而且修复后的代码:


而且修复后的代码:

#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Ord, PartialOrd, Eq)]
pub struct WeightWithOptionGroup {
    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub group: Option<String>,
    #[serde(skip_serializing_if = "is_zero")]
    #[serde(default)]
    pub proportion: u32,
}

/// This is only used for serialize
#[allow(clippy::trivially_copy_pass_by_ref)]
fn is_zero(num: &u32) -> bool {
    *num == 0
}

3

你可以采取以下两种方法:

  • 使用skip_serialising_if属性标记每个字段以指定何时跳过它们。这种方法比较简单,但你需要记住为每个字段都这样做。
  • 编写自己的 Serde 序列化器来生成此自定义 JSON 形式。虽然这种方法需要更多工作,但不会太麻烦,尤其是因为你仍然可以使用默认的 JSON 反序列化器。

1

对于那些想要跳过某些枚举条目序列化的人,可以这样做

#[derive(Serialize, Deserialize)]
enum Metadata<'a> {
  App,             // want this serialized
  Ebook,           // want this serialized
  Empty            // dont want this serialized
}

#[derive(Serialize, Deserialize)]
struct Request<'a> {
    request_id: &'a str,
    item_type: ItemType,
    #[serde(skip_serializing_if = "metadata_is_empty")]
    metadata: Metadata<'a>,
}

fn metadata_is_empty<'a>(metadata: &Metadata<'a>) -> bool {
  match metadata {
    Metadata::Empty => true,
    _ => false
  }
}

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