llxxbb
llxxbb

Reputation: 1871

How do I avoid generating JSON when serializing a value that is null or a default value?

The serde_json::to_string() function will generate a string which may include null for an Option<T>, or 0 for a u32. This makes the output larger, so I want to ignore these sorts of values.

I want to simplify the JSON string output of the following structure:

use serde_derive::Serialize; // 1.0.82

#[derive(Serialize)]
pub struct WeightWithOptionGroup {
    pub group: Option<String>,
    pub proportion: u32,
}

When group is None and proportion is 0, the JSON string should be "{}"

Thanks for the answerHow do I change Serde's default implementation to return an empty object instead of null?, it can resolve Optionproblem, but for 0 there is none solution.

Upvotes: 51

Views: 32604

Answers (3)

thiagoh
thiagoh

Reputation: 7388

For those searching how to skip serialization for some enum entries you can do this

#[derive(Serialize, Deserialize)]
enum Metadata {
  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,
}

impl Metadata {
    fn is_empty(&self) -> bool {
        match self {
            Metadata::Empty => true,
            _ => false,
        }
    }
}

Upvotes: 8

llxxbb
llxxbb

Reputation: 1871

The link Skip serializing field give me the answer.

And the fixed code:

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

Upvotes: 94

Tom Parker-Shemilt
Tom Parker-Shemilt

Reputation: 1697

There's a couple of ways you could do this:

  • Mark each of the fields with a skip_serialising_if attribute to say when to skip them. This is much easier, but you'll have to remember to do it for every field.
  • Write your own Serde serialiser that does this custom JSON form. This is more work, but shouldn't be too bad, especially given you can still use the stock JSON deserialiser.

Upvotes: 3

Related Questions