Call the replacer *before* the object's toJSON

2019-03-16 18:10发布

Is there a way to get my replacer called before an object's own toJSON transforms it, so that I can work with the original object rather than its JSON-friendly form, without overriding the toJSON on the object or its prototype, pre-processing the object, or writing my own version of JSON.stringify?

For example: Suppose I want to serialize Date instances differently than their normal serialization (which is toISOString). (This question is not specific to Date, this is just an example.) The problem is, my replacer doesn't see the Date object, it sees a string (see snippet below) because Date.prototype.toJSON is called before my replacer.

var obj = {
  d: new Date()
};
snippet.log(getType(obj.d));     // "[object Date]"

var json = JSON.stringify(obj, function(key, value) {
  if (key === "d") {
    snippet.log(getType(value)); // "string" <== Want to see a Date here
  }
  return value;
});

function getType(value) {
  var to = typeof value;
  if (to === "object") {
    to = Object.prototype.toString.call(value);
  }
  return to;
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Is there a way to get the replacer called first? I don't want to override Date.prototype.toJSON, pre-process the object, or write my own JSON.stringify, but I'm not seeing another way.

2条回答
Summer. ? 凉城
2楼-- · 2019-03-16 18:20

From MDN:

The object in which the key was found is provided as the replacer's this parameter.

So you can do this:

var obj = {
  d: new Date()
};
snippet.log(getType(obj.d));     // "[object Date]"

var json = JSON.stringify(obj, function(key, value) {
  if (key === "d") {
    snippet.log(getType(this[key]));
  }
  return value;
});

function getType(value) {
  var to = typeof value;
  if (to === "object") {
    to = Object.prototype.toString.call(value);
  }
  return to;
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

查看更多
ゆ 、 Hurt°
3楼-- · 2019-03-16 18:34

If I understand you correct this should do the trick, I'm pretty sure this is always the object JSON.stringify is currently iterating over:

var json = JSON.stringify(obj, function(key, value) {
  if (key === "d") {
    snippet.log(getType(this[key]));
  }
  return value;
});
查看更多
登录 后发表回答