One recurring debate when designing JSON APIs is how to represent missing or optional data: should a response (or request) include "middle_name": null, or omit the "middle_name" key altogether?

// Option A: explicit null
{
  "id": "usr_123",
  "first_name": "Albert",
  "middle_name": null
}

// Option B: omit empty / absent fields
{
  "id": "usr_123",
  "first_name": "Albert"
}

Both approaches are valid JSON, and the right choice depends on whether you are designing response payloads (GET) or partial update payloads (PATCH).

null vs. Empty Values ("", 0, [])

First, null is not a substitute for an empty collection or an empty string:

  • Arrays/collections should almost never be null in responses. Returning "items": [] instead of "items": null saves every client from writing null checks before iterating. (In Go, initialize slices with make([]Item, 0) or []Item{} rather than var items []Item, which marshals to null.)
  • Booleans and numbers should only be nullable when “unknown / not set” has a real domain meaning distinct from false or 0.

When Returning Explicit null Makes Sense

  1. Predictable response shape: Consumers inspecting the payload see the full schema at a glance without checking the OpenAPI spec to know a field exists.
  2. Distinguishing “not set” from “not requested”: In APIs that support field selection (?fields=id,first_name), an omitted key means the caller didn’t ask for it, whereas "middle_name": null means the caller asked for it and the value is empty.
  3. JSON Merge Patch (PATCH — RFC 7396): In a partial update, omitting a field means “leave this field untouched”, whereas sending "middle_name": null means “clear the existing value”.

When Omitting Empty Fields Makes Sense

  1. Smaller payloads: On wide resources with dozens of optional attributes, stripping unset fields via omitempty (or omitzero in Go 1.24+) reduces payload size over the wire.
  2. Forward/backward compatibility: Adding a new optional attribute doesn’t change existing responses until that feature is populated.
  3. Simpler client defaults: Languages like TypeScript (user.middleName ?? "N/A") treat undefined cleanly when keys are omitted, whereas null does not trigger default parameters (function greet(name = "Guest") still receives null if null is passed!).

Practical Rules of Thumb

  • Never return null for arrays or objects that represent collections—return [] or {}.
  • Be consistent across responses: Pick either explicit null for nullable scalar fields or omitted keys across your API, and document nullable: true vs required accurately in your OpenAPI specification.
  • In PATCH endpoints, treat omitted and null differently: Use pointer fields or a 3-state wrapper (Unset, Null, Value) on the backend so you can tell whether the client omitted the key or explicitly sent null to clear it.