All posts

Rust / Skip some fields when serializing

Posted On 03.21.2022

Using serde, we can serialize a data structure into different formats, for example, JSON:

#[derive(Serialize)]
struct Author {
    id: i32,
    name: String
}
 
#[derive(Serialize)]
struct Note {
    title: String,
    content: String,
    author: Option<Author>
}
 
fn main() {
    let note = Note {
        title: String::from("Hello, World!"),
        content: String::from("Lorem ipsum doro note note!"),
        author: Some(Author {
            id: 1,
            name: String::from("Huy")
        })
    };
    
    println!("{}", serde_json::to_string_pretty(&note).unwrap());
}

Output:

{
  "title": "Hello, World!",
  "content": "Lorem ipsum doro note note!",
  "author": {
    "id": 1,
    "name": "Huy"
  }
}

Sometimes, we need to exclude some fields from the original data structure when serializing.

To do so, we can annotate a field with skip_serializing to exclude it during the serializing process.

Note that, skip_serializing only skip serializing, but serde still trying to deserialize the field. To skip deserializing, use skip_deserializing. Or we can just use skip for both.

#[derive(Serialize)]
struct Note {
    title: String,
    content: String,
    #[serde(skip)]
    author: Option<Author>
}

Output:

{
  "title": "Hello, World!",
  "content": "Lorem ipsum doro note note!",
}

Also, you can skip a field conditionally, with skip_serializing_if, for example:

#[derive(Serialize)]
struct Note {
    title: String,
    content: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    author: Option<Author>
}

If the author field is a Some value, things works normally:

let note = Note {
    title: String::from("Hello, World!"),
    content: String::from("Lorem ipsum doro note note!"),
    author: Some(Author {
        id: 1,
        name: String::from("Huy")
    })
};

Output:

{
  "title": "Hello, World!",
  "content": "Lorem ipsum doro note note!",
  "author": {
    "id": 1,
    "name": "Huy"
  }
}

But if the author is None, it will be skipped:

let note = Note {
    title: String::from("Hello, World!"),
    content: String::from("Lorem ipsum doro note note!"),
    author: None
};

Output:

{
  "title": "Hello, World!",
  "content": "Lorem ipsum doro note note!",
}