JSON has null. JSON does not have undefined. This single fact causes a class of bugs where fields silently vanish from API payloads, objects arrive with missing keys, or arrays gain unexpected null slots — and no error is ever thrown.
Inspecting a JSON payload with null values? Format and validate it instantly:
The six value types JSON defines
The JSON specification (RFC 8259) defines exactly six value types: string, number, boolean (true/false), null, object, and array. undefined is not on this list.
undefined is a JavaScript-specific primitive that means "a variable was declared but never assigned." Because JSON must be portable across every programming language, it can only carry concepts every language can represent. undefined has no equivalent in Python, Java, Go, or Rust — so it was intentionally excluded from the spec.
What JSON.stringify does with undefined
There are three different places an undefined can appear, and JSON.stringify handles each differently.
Case 1 — top-level undefined
JSON.stringify returns the JS primitive undefined — not the string "undefined", not "null", not an empty string. Nothing is serialised.
JSON.stringify(undefined); // → undefined (not a string!)
typeof JSON.stringify(undefined); // → "undefined"
// This means it cannot be used as a fetch body:
const body = JSON.stringify(undefined);
console.log(body); // undefined — nothing useful is sent
Case 2 — object property with an undefined value
The key is silently omitted from the output. No error, no warning. This is the most common source of bugs — a field is set to undefined expecting it to be included in a request body, but it never reaches the server.
const user = {
name: "Alice",
age: undefined, // ← will be dropped
role: "admin",
token: undefined, // ← will be dropped
};
JSON.stringify(user);
// → '{"name":"Alice","role":"admin"}'
// age and token are gone silently
Case 3 — array element is undefined
Array elements are replaced with null to preserve the array's indices. The length of the output array matches the original.
JSON.stringify([1, undefined, 3, undefined]);
// → '[1,null,3,null]'
// Also happens with holes in sparse arrays:
const sparse = [1,,3];
JSON.stringify(sparse);
// → '[1,null,3]'
Summary table
Location of undefined | JSON.stringify output | Effect |
|---|---|---|
| Top-level value | undefined (JS primitive) | Nothing serialised |
| Object property value | Key omitted entirely | Silent data loss |
| Array element | Replaced with null | Length preserved; value lost |
Property returned by toJSON() | Key omitted entirely | Same as object property rule |
null vs undefined in JavaScript
let a; // declared but not assigned → undefined
let b = null; // explicitly assigned "no value"
typeof a; // "undefined"
typeof b; // "object" ← historical quirk of JS
a == b; // true (loose equality — both are "nothing")
a === b; // false (strict equality — different types)
In JSON terms: null serialises cleanly to null; undefined triggers the silent-drop behaviour above.
What about JSON.parse?
JSON.parse can never produce undefined as a value — because undefined is not in the JSON spec. If the JSON text contains null, you get JavaScript null. If a key is simply absent, accessing it on the resulting object gives you JavaScript undefined (the language's default for missing keys), but that is not something JSON put there.
const parsed = JSON.parse('{"name":"Alice","age":null}');
parsed.age; // null ← JSON null, parsed as JS null
parsed.email; // undefined ← key absent; JS default for missing keys
parsed.age === null; // true
parsed.email === undefined; // true — but the key was never in the JSON
How to preserve undefined values — convert to null
If you want every key sent — even those currently undefined — convert them to null using a replacer function:
const user = {
name: "Alice",
age: undefined,
role: "admin",
};
const json = JSON.stringify(user, (key, value) =>
value === undefined ? null : value
);
console.log(json);
// → '{"name":"Alice","age":null,"role":"admin"}'
// All keys present; undefined replaced with null
The server now receives every field. It can distinguish "not provided" (null) from "field was removed from the schema" (key absent) — important for PATCH endpoints.
Detecting null vs missing key in parsed JSON
Once you have parsed a JSON payload, use key in obj — not obj[key] !== undefined — to tell whether a field was explicitly set to null or simply not sent:
const a = JSON.parse('{"name":"Alice","age":null}');
const b = JSON.parse('{"name":"Alice"}');
"age" in a; // true — key was sent, value is null
"age" in b; // false — key was never included
a.age; // null
b.age; // undefined ← JS default, not from JSON
How other languages handle JSON null
| Language | JSON null maps to | Equivalent of JS undefined |
|---|---|---|
| JavaScript | null | undefined (absent key) |
| Python | None | No equivalent — absent key raises KeyError |
| Java (Jackson) | null | No equivalent — absent key = default field value |
| Go | nil (pointer/interface) | No equivalent — absent key = zero value |
| Rust (serde) | None (Option<T>) | No equivalent — absent key = None |
Python
import json
data = {"name": "Alice", "age": None}
print(json.dumps(data))
# → '{"name": "Alice", "age": null}'
parsed = json.loads('{"name": "Alice", "age": null}')
print(parsed["age"]) # None
print("missing" in parsed) # False — use `in` to distinguish absent from null
Java + Jackson
// Jackson serialises Java null → JSON null
// Use @JsonInclude to control whether null fields are sent:
@JsonInclude(JsonInclude.Include.NON_NULL)
public class User {
public String name;
public Integer age; // null → field omitted from JSON output
}
Common bugs caused by this distinction
Bug 1 — optional field never reaches the server
// ❌ Bug: clearing a field by setting it to undefined
const patch = { name: "Alice", nickname: undefined };
await fetch("/api/user/1", { method: "PATCH", body: JSON.stringify(patch) });
// Server receives: {"name":"Alice"} — nickname was never sent
// ✅ Fix: use null to explicitly signal "clear this field"
const patch = { name: "Alice", nickname: null };
// Server receives: {"name":"Alice","nickname":null} — field cleared
Bug 2 — short-circuit expression produces undefined
// ❌ Bug: if discount is null, discount.code is never reached,
// the && returns null, which is fine — but what if discount
// is an object without a .code property? Returns undefined.
const payload = {
userId: 42,
couponCode: discount && discount.code, // could be undefined!
};
JSON.stringify(payload);
// → '{"userId":42}' — couponCode silently dropped
// ✅ Fix: default to null
const payload = {
userId: 42,
couponCode: (discount && discount.code) ?? null,
};
Bug 3 — loose equality check conflates null and undefined
const data = JSON.parse('{"name":"Alice"}');
// ⚠️ Both null and undefined pass == null — you can't tell which
if (data.age == null) {
console.log("age is null or undefined"); // true — but which?
}
// ✅ Be explicit
if (data.age === null) {
console.log("age was sent as null");
} else if (!("age" in data)) {
console.log("age was not included in the response");
}
null in JSON Schema
JSON Schema has a null type for nullable fields. There is no undefined keyword — optional fields are expressed by omitting them from required:
{
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": ["integer", "null"] } // integer or explicitly null
},
"required": ["name"]
// "age" is optional — if absent, key simply does not appear
}
Quick reference
| Scenario | Result |
|---|---|
JSON.stringify(undefined) | undefined (JS primitive, not a string) |
JSON.stringify({a: undefined}) | '{}' — key silently dropped |
JSON.stringify([undefined]) | '[null]' — replaced to preserve index |
JSON.stringify(null) | 'null' — valid JSON |
JSON.parse('null') | null (JS) |
Access absent key after JSON.parse | undefined — JS default, not from JSON |
Convert undefined → null | JSON.stringify(obj, (k, v) => v === undefined ? null : v) |
| Distinguish absent vs null in parsed object | 'key' in obj (not obj.key !== undefined) |
Frequently Asked Questions
Does JSON support undefined?
No. The JSON specification defines exactly six value types: string, number, boolean (true/false), null, object, and array. undefined is a JavaScript concept — it does not exist in JSON and cannot be represented in a JSON document.
What happens when you JSON.stringify undefined?
It depends on location. At the top level, JSON.stringify(undefined) returns the JS primitive undefined (not a string). As an object property, the key is silently omitted. As an array element, it is replaced with null to preserve the array's length.
What is the difference between null and undefined in JSON?
null is a valid JSON value — it explicitly represents "no value." undefined does not exist in JSON. When a JavaScript object has a property set to undefined and is serialised with JSON.stringify, that property is dropped entirely from the output string.
How do I keep undefined values in JSON output?
Use a replacer function: JSON.stringify(obj, (key, val) => val === undefined ? null : val). This converts all undefined values to null, keeping every key in the output.
What does null mean in JSON Schema?
JSON Schema has a null type for nullable fields: type: ["string", "null"]. There is no undefined keyword — optional fields are expressed by omitting them from the required array.
Format and validate your JSON in the browser
Paste any JSON payload to pretty-print it, spot null fields, or validate the structure — no data is sent to a server.
Need to inspect a payload with null values right now? Pretty-print it in the browser.
Open JSON Formatter →