为什么JSON.stringify会忽略其值未定义的键?

时间:2015-07-08 05:31:14

标签: javascript json

为了更准确,我理解为什么技术上发生 - 因为undefined不是有效的JSON类型:

var breakfast = {
    "cereal" : "fruit loops",
    "pastry" : undefined
};

console.log(breakfast);
// -> { cereal: 'fruit loops', pastry: undefined }

console.log(JSON.stringify(breakfast));
// -> {"cereal":"fruit loops"}

我的问题是 - 为什么这被认为是可接受的行为?我有理由将undefined作为API或其他任何内容的一部分传递。这似乎有些危险 - 为什么函数不会引发错误而不是肆无忌惮地在没有警告的情况下更改我的数据?这似乎是JS的一个运行线程。

2 个答案:

答案 0 :(得分:6)

答案在于ECMA-262 spec。在24.3.2 JSON.stringify ( value [ , replacer [ , space ] ] )部分中,规范明确指出:

  

注2

     

未呈现未定义值。

此外:

  

注5

     

没有JSON表示的值(例如未定义和函数)不会生成String。相反,他们生产   未定义值。在数组中,这些值表示为   字符串 null 。在对象中,不可代表的值会导致该属性   被排除在字符串化之外。

因此,JSON.stringify()正如您使用它完全符合现有的ECMA规范。

即使使用替换程序,而没有专门指定您自己的函数,默认的替换程序规则也指出只应追加 items

  

24.3.2第4.b.5.g小节

     

如果不是未定义目前不是   对propertyList

答案 1 :(得分:3)

JSON意味着与语言无关。它已经支持null。支持undefined也会强制处理JavaScript在其他语言上的特性之一,这会破坏易于互操作的目的。

'JSON's design goals were for it to be minimal, portable, textual, and a subset of JavaScript.'

至于没有抛出错误,那么

var x = { foo: undefined };
x.foo === undefined; // true
var json = JSON.stringify(x);
var y = JSON.parse(json);
y.foo === undefined; // true

因此JSON.stringify 可以创建一个代表值x的字符串。 在这种情况下,抛出错误不会有用。实际上是JSON.stringify 忽略所有没有JSON表示的值,所以函数 被忽略了。例如,这使得序列化对象数据变得容易。

最后,请记住JSON.stringify采用replacer函数 一个参数,可用于改变字符串化的发生方式。 因此,要使JSON.stringify抛出具有undefined值的现有属性:

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

或者替换为null

var replacer = function(key, value){
    if(value === undefined){
        return null;
    }
    return value;
};

var x = {foo: undefined};
JSON.stringify(x, replacer); // '{"foo":null}'