Option<T> for Nullable JSON Fields

Wrap fields that can be null in Option<T>. Learn how serde handles missing keys, explicit null, and the difference between the two.

Type Mapping

Detailed Explanation

Modeling Nullable Fields with Option

Rust does not have a native null. The idiomatic way to represent "this value may or may not exist" is Option<T>, where Some(value) is a present value and None is missing.

Example JSON

{
  "id": 1,
  "nickname": "ada",
  "deleted_at": null
}

Generated Rust

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Root {
    pub id: i32,
    pub nickname: String,
    pub deleted_at: Option<serde_json::Value>,
}

Refining the inner type

The converter cannot guess the type behind null. Replace Option<serde_json::Value> with the actual type once you know it:

pub deleted_at: Option<chrono::DateTime<Utc>>,

Missing keys vs explicit null

By default, serde treats a missing key as a deserialization error. To accept either a missing key or null, add the default attribute:

#[serde(default)]
pub deleted_at: Option<DateTime<Utc>>,

Now the field becomes None whether the key is absent or present-and-null.

Skipping null on serialization

To avoid emitting "deleted_at": null when the value is None, combine Option<T> with #[serde(skip_serializing_if = "Option::is_none")]:

#[serde(skip_serializing_if = "Option::is_none")]
pub deleted_at: Option<DateTime<Utc>>,

This is the standard pattern for PATCH request bodies, sparse REST responses, and database update payloads where you do not want to overwrite columns with NULL.

Use Case

Soft-deleted database rows, optional metadata, and partial PATCH update payloads all rely on Option<T>. Getting the pattern right is the difference between safe round-trips and accidental data loss.

Try It — JSON to Rust Struct Converter

Open full tool