最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why does JSON.stringify ignore keys whose values are undefined? - Stack Overflow

programmeradmin2浏览0评论

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.

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.

Share Improve this question edited Jul 8, 2015 at 5:37 Mark asked Jul 8, 2015 at 5:31 MarkMark 12.5k6 gold badges24 silver badges38 bronze badges 6
  • 5 JSON contains only strings. If a value is undefined it would also have to be converted to a string. What happens if I'm going to transfer a string which has the same value as the string-representation of undefined? How to distinguish which "undefined" is which. But if you really want to go this way then you can pass a replacer function as the second parameter of JSON.stringify(value[, replacer[, space]]) -> developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… – Andreas Commented Jul 8, 2015 at 5:38
  • Like I said in the question, I understand the mechanics of what is going on - but I am unsatisfied as to why it does it. The function you link to is obviously a solution, but is not something that I believe should be required for this in the first place :) Also as a side note, JSON contains other data types, not only strings (bools, arrays) – Mark Commented Jul 8, 2015 at 5:39
  • You're right for bools and numbers. But arrays are also translated into their string representation. undefined is not a defined value for JSON. If you really need to change the defined behaviour of JSON then you will have to use a replacer function. – Andreas Commented Jul 8, 2015 at 5:47
  • Ah ok. I don't want to change the behaviour of JSON, I want to change the JSON.stringify method accordingly to reflect JSON's limitations. To clarify - I know how to do to this, what I'm saying is this should be default behaviour. – Mark Commented Jul 8, 2015 at 5:49
  • 3 Seems to me this is actually a question for a JSON discussion group and has nothing to do with JavaScript (other than the J in JSON). Perhaps remove the javascript tag? – RobG Commented Jul 8, 2015 at 5:53
 |  Show 1 more comment

2 Answers 2

Reset to default 10

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}'
发布评论

评论列表(0)

  1. 暂无评论