简体   繁体   English

带有替换功能的JSON.stringify中的奇怪行为

[英]Strange behaviour in JSON.stringify with replacer function

Consider this: 考虑一下:

var object = {date: new Date()};

JSON.stringify(object, function(key, value) {
    console.log('---');
    console.log('key:', key);
    console.log('value:', value);
    console.log('value instanceof Date:', value instanceof Date);

    return value;
});

As documentation says: 文档所述

The replacer parameter can be either a function or an array. replacer参数可以是函数或数组。 As a function, it takes two parameters, the key and the value being stringified. 作为一个函数,它需要两个参数,即键和值被字符串化。 The object in which the key was found is provided as the replacer's this parameter. 在其中找到密钥的对象作为替换者的this参数提供。 Initially it gets called with an empty key representing the object being stringified, and it then gets called for each property on the object or array being stringified. 最初,它使用表示要被字符串化的对象的空键调用,然后针对要被字符串化的对象或数组的每个属性调用它。

... ...

If you return any other object, the object is recursively stringified into the JSON string, calling the replacer function on each property, unless the object is a function, in which case nothing is added to the JSON string. 如果返回任何其他对象,则将该对象递归地字符串化为JSON字符串,并在每个属性上调用replacer函数,除非该对象是一个函数,在这种情况下,不会将任何内容添加到JSON字符串。

But if you run the code, you will get this: 但是,如果您运行代码,则会得到以下信息:

---
key: 
value: { date: Fri Jan 10 2014 02:25:00 GMT+0100 (CET) }
value instanceof Date: false
---
key: date
value: 2014-01-10T01:25:00.262Z
value instanceof Date: false

It means, that the date property was stringified before replacer function has been called. 这意味着,在调用replacer函数之前,已对date属性进行了字符串化。 Is it a normal behaviour or am I missing something? 这是正常行为还是我错过了一些东西? How can I affect format of Date stringification without overriding it's default toJSON method? 如何在不覆盖默认的toJSON方法的情况下影响Date字符串化的格式?

Thanks! 谢谢!

Edit 编辑

Based on responses and next research, documentation seems to be unclear at this point and toJSON is beeing called before the replacer function. 根据响应和下一步研究,目前文档尚不清楚,并且在替换函数之前先调用toJSON Based on Pills's response, this snippet should do the job: 根据Pills的回复,此代码段应完成以下工作:

var object = {date: new Date };

JSON.stringify(object, function(key, value) {
    if (typeof(value) === 'object') {
        for (var k in value) {
            if (value[k] instanceof Date) {
                value[k] = value[k].getTime();
            }
        }
    }
    return value;
});

Edit #2 编辑#2

Xotic750's solution is much better than previous one. Xotic750的解决方案比以前的解决方案好得多。

Perhaps you could do your formatting before passing the object to JSON , but otherwise here is a possibility: 也许您可以在将对象传递给JSON之前进行格式化,否则可能会出现这种情况:

JSON uses an objects toJSON method before calling the replacer. JSON在调用toJSON之前使用对象toJSON方法。

So, before calling stringify store the toJSON method and then restore it afterwards. 因此,在调用stringify之前,存储toJSON方法,然后再将其还原。

var object = {
        date: new Date()
    },
    storeToJSON = Date.prototype.toJSON;

delete Date.prototype.toJSON;

JSON.stringify(object, function (key, value) {
    console.log('---');
    console.log('key:', key);
    console.log('value:', value);
    console.log('value instanceof Date:', value instanceof Date);

    return value;
});

Date.prototype.toJSON = storeToJSON;

On jsFiddle jsFiddle上

Its quiet old but just to complete it. 它很安静,但只是为了完成它。

According to this Q/A and the MDN JSON.stringify article , the replacer is called with instance of the object in which the key was found so no need to change prototype or do another tricks: 根据此Q / AMDN JSON.stringify文章 ,将使用在其中找到了密钥的对象的实例调用替换程序,因此无需更改原型或进行其他操作:

 function log(what) { what = what || ""; document.getElementById("out").innerText += what + "\\n"; } function replacer(key, value) { console.log(this); log("Key: '" + key + "' = '" + value + "'"); log("this = " + this); log("this[key] = " + this[key]); log("this[key] instanceof Date = " + (this[key] instanceof Date)); log("this instanceof Date = " + (this[key] instanceof Date)); if (this[key] instanceof Date) { return "This was a date: " + this[key].getTime(); } return value; } var obj = { d: new Date() }; var result; result = JSON.stringify(new Date(), replacer); log(); log(result); log(); result = JSON.stringify(obj, replacer); log(); log(result); 
 <pre id="out"></pre> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM