To be more accurate, I understand why this technically happens - since undefined
is not a valid JSON type:
var breakfast = {
"cereal" : "fruit loops",
"pastry" : undefined
};
console.log(breakfast);
// -> { cereal: 'fruit loops', pastry: undefined }
console.log(JSON.stringify(breakfast));
// -> {"cereal":"fruit loops"}
My question is - why is this considered acceptable behaviour? There are clearly valid reasons why I would want to pass undefined
as part of an API or whatever. This seems somewhat dangerous - why wouldn't the function raise an error instead of brazenly taking it upon itself to change my data without warning? This seems like a bit of a running thread with JS.
JSON. stringify will omit all object attributes that are undefined .
Undefined is not a valid JSON type. All javascript objects are not valid JSON and vice versa. All other values will be sent to the response but undefined won't be sent.
undefined , Function , and Symbol values are not valid JSON values. If any such values are encountered during conversion, they are either omitted (when found in an object) or changed to null (when found in an array).
The answer to this lies in the ECMA-262 spec. In section 24.3.2 JSON.stringify ( value [ , replacer [ , space ] ] )
, the spec clearly states that:
NOTE 2
The undefined value is not rendered.
Further:
NOTE 5
Values that do not have a JSON representation (such as undefined and functions) do not produce a String. Instead they produce the undefined value. In arrays these values are represented as the String null. In objects an unrepresentable value causes the property to be excluded from stringification.
Thus, JSON.stringify()
as you are using it is perfectly following the existing ECMA spec.
Even using a replacer, without specifically specifying your own function, the default replacer rules state that items should only be appended:
24.3.2 Subsection 4.b.5.g
If item is not undefined and item is not currently an element of PropertyList
JSON is meant to be language agnostic. It already supports null
. Supporting undefined
as well would impose the handling of one of JavaScript's idiosyncrasies on other languages, which defeats the purpose of easy interoperability.
'JSON's design goals were for it to be minimal, portable, textual, and a subset of JavaScript.'
As for not throwing an error, well
var x = { foo: undefined };
x.foo === undefined; // true
var json = JSON.stringify(x);
var y = JSON.parse(json);
y.foo === undefined; // true
So JSON.stringify
can create a string that represents the value x
.
Throwing an error would not be useful in this case. In fact JSON.stringify
ignores all values that don't have a JSON representation, so functions
are ignored to. This makes it easy to serialise object data, for example.
Finally, bear in mind that JSON.stringify takes a replacer
function as
an argument which can be used to alter the way stringification takes place.
So to make JSON.stringify
throw existing properties with an undefined
value:
var replacer = function(key, value){
if(value === undefined){
throw 'JSON.stringify: bad property: ' + key;
}
return value;
};
var x = {foo: undefined};
JSON.stringify(x, replacer);
// uncaught exception: JSON.stringify: bad property: foo
Or to replace with null
:
var replacer = function(key, value){
if(value === undefined){
return null;
}
return value;
};
var x = {foo: undefined};
JSON.stringify(x, replacer); // '{"foo":null}'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With