<html>
<body>
<script src="core.min.js"></script>
<script>
var myObject = {
map: new Map([["en", "foo"]])
}
function replacer(name, val) {
console.log(val);
if ( val instanceof Map ) {
return {"en": "foo"};
} else {
return val; // return as is
}
};
var json = JSON.stringify(myObject, replacer, 4);
console.log(json);
</script>
</body>
</html>
The output is:
Object { map=Map}
[["en", "foo"]]
["en", "foo"]
en
foo
{
"map": [
[
"en",
"foo"
]
]
}
Without core-js it is:
Object { map=Map}
Map {}
foo
{
"map": {
"en": "foo"
}
}
Expected behavior. Stage 0 proposal.
I don't understand this. The replacer function is meant for taking action _before_ serializing to JSON, so it should receive the original value, in that case the Map object, which also happens when the polyfill is not active. I agree that a default JSON serialization for Map and Set is useful, but this is not what this issue is about.
Thanks for pointing me there. You're right, it is as expected, but I have to say I find this algorithm really a bit unintuitive and actually dangerous since it may break your code at any time if someone decides to put a toJSON function to a prototype whose transformation you have handled manually before. Apart from that, with this stage 0 proposal and the algorithm you linked to there is no way to detect that a value had been a Map, since it is just a nested array now. Am I missing something? Do you agree or disagree and do you think I should raise this issue somewhere?
@neothemachine why do you need to know if it's a Map or an array of entries? Any issues caused by serializing the Map would be present in the entries array (namely, a key or value you couldn't serialize).
Well, because I want to serialize Map's as simple objects because I know that they have strings as keys.
@neothemachine if you have a subset of Map and want special behavior for it then you absolutely can't rely on toJSON here. I'd recommend either just using a normal object, or (if you want the Map API), use a subclass of Map that only allows string keys and has a custom toJSON implementation on its prototype.
@ljharb Ok I accept that, but I still don't like the general approach of how toJSON works together with stringify (so my concern is not related to core-js at all in the end). It seems a bit strange to me that the encoding in one specific JSON format is so tightly coupled to the model object. What if I have two different JSON formats and want to serialize my object in both? Then I would have to recreate the whole object hierarchy with the different set of Map subclasses just to get the encoding right. Typically the encoder part is separate and I thought this is exactly what the replacer function is good for. I think separation of concerns is not really solved well here, but it works for the majority of cases I guess.
It seems the proposal has been rejected.
@larsgw so it was removed from core-js@3.
Right, sorry. I still saw the behaviour in @babel/polyfill, which I thought was up to date.