Code Beautifier
missing field `email`

Fix serde "missing field `email`"

serde_json fails when a struct field has no matching key. Why non-Option fields are mandatory, when to use Option<T> or #[serde(default)], and the fix.

Input that triggers it

[{"id": 1, "email": "ada@example.com"}, {"id": 2}]
Open JSON to Rust on its own page
Draft saved locally.

Local workspace

Named projects in IndexedDB · Local only — never synced to our servers. Worksp

Open manager

Batch workspace

Format multiple files locally in one run.

json
Rustrust

What the error means

serde's derived Deserialize treats every struct field as required unless told otherwise. When the JSON object has no key for a field, deserialization fails with missing field \email` at line 1 column 9` — the position is where the object ended, because that is when serde knew the field was never coming. There is no partial struct; the whole value is rejected.

In the example, the first record contains email and the second does not. A struct generated from the first record declares email: String, which makes the key mandatory, so the second record fails.

Why it happens

  • The generation sample always contained the key.
  • The key is optional in the producer's contract, present for some records and absent for others.
  • A field that is nullable but not optional. email: Option<String> accepts "email": null and an absent key — serde treats a missing Option field as None by default — but a field of type String does not, and neither does a custom type without #[serde(default)].
  • A rename mismatch: the JSON key is user_email and the field is email without #[serde(rename = "user_email")], so the key is present but unmatched.

How to fix it

  1. Paste a sample that includes a record without the key into the generator above. It merges the records and emits Option<String> for any field absent from at least one; serde then decodes an absent key as None with no further annotation.
  2. In an existing struct, change the type to Option<String>, or keep the type and add #[serde(default)] to fall back to Default::default() — an empty string, zero, an empty vector — when the key is missing.
  3. For a specific fallback, use #[serde(default = "path::to::fn")].
  4. If the JSON key has a different name, add #[serde(rename = "...")] or a struct-level #[serde(rename_all = "camelCase")] rather than renaming the field.

The struct that accepts both records:

use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Root {
    pub id: i64,
    pub email: Option<String>,
}

If it still fails

  • #[serde(deny_unknown_fields)] is the opposite concern — it rejects extra keys — and does not interact with this error.
  • If the message names a field inside a nested struct, the Option or default belongs on the inner struct's field.
  • Go and Kotlin apply the same required-by-default rule; JSON to Go uses pointers with omitempty and JSON to Kotlin uses T? = null for the same optional key.

Related errors