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

Mar*_*ark 7 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"}
Run Code Online (Sandbox Code Playgroud)

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

Mat*_*bst 7

答案就在于ECMA-262规范.在章节中24.3.2 JSON.stringify ( value [ , replacer [ , space ] ] ),规范明确指出:

笔记2

未定义值不会被渲染.

进一步:

注5

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

因此,JSON.stringify()正如您所使用它完全遵循现有的ECMA规范.

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

24.3.2第4.b.5.g小节

如果项目不是不确定项目不是当前的元素 对propertyList


198*_*983 6

JSON 旨在与语言无关。它已经支持null. 支持undefined也会将 JavaScript 的一种特性强加于其他语言,这违背了轻松互操作性的目的。

“JSON 的设计目标是最小化、可移植、文本化和 JavaScript 的子集。”

至于不抛出错误,好吧

var x = { foo: undefined };
x.foo === undefined; // true
var json = JSON.stringify(x);
var y = JSON.parse(json);
y.foo === undefined; // true
Run Code Online (Sandbox Code Playgroud)

因此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
Run Code Online (Sandbox Code Playgroud)

或者替换为null

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

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