除了 Set 和 Map,还有哪些常见的 JS 类不能很好地与 JSON.stringify() 配合使用?



当我们在 Map 或 Set 上调用 JSON.stringify 时,我们得到空数据:

console.log(JSON.stringify({foo: new Map([[1,2], [3,4]])}));

我们只是得到:

{"foo":{}}

我可以使用以下方法或多或少地解决上述问题:

console.log(JSON.stringify({foo: Array.from(new Map([[1,2], [3,4]]))}));

但我的问题是- 除了 Map 和 Set 之外,还有其他核心 JS 类不会自动序列化吗?

JSON 仅支持:字符串、数字、布尔值、null 和数组以及以这些作为值/属性的普通对象。就是这样。因此,JSON 不直接支持由任何其他对象组成的其他类型的对象。

您必须手动将对象转换为可以在 JSON 中使用这些基本类型表示的内容,或者找到其他方法来表示对象。对象中的数据(如具有简单值/索引的 Map(可以手动放入 JSON 形式(可能是在对象数组或数组数组中(,但在反序列化时将其转换回 Map 必须手动完成。

您可以在此处查看 JSON 支持的类型:https://www.json.org/

这意味着任何自定义对象类型(即使其实例数据仅由上述类型组成(也不会反序列化为正确的对象类型。 这甚至包括像DateRegex这样的东西,当然也包括任何非普通对象,如SetMap

可以手动将数据转换为 JSON 可序列化的内容,然后手动反序列化为相应的对象。 例如,您可以序列化仅包含合法键和值的非嵌套MapSet,如下所示:

function serialize(mapOrSet) {
if (mapOrSet instanceof Map) {
// convert Map into 2D array
// [[key1, val1], [key2, val2], ....]
let data = [];
for (const [key, value] of mapOrSet) {
data.push([key, value]);
}
return JSON.stringify({
_customType: "Map",
_data: data
});
} else if (mapOrSet instanceof Set) {
return JSON.stringify({
_customType: "Set",
_data: Array.from(mapOrSet);
}); 
} else {
throw new TypeError("argument to serialize() must be Map or Set");
}
}

然后,您必须有一个自定义反序列化程序,该反序列化程序可以检测具有_customType属性的对象,并调用适当的反序列化程序函数将纯 JSON 转换为适当的自定义对象类型。 您甚至可以通过让对象支持其自己的序列化和反序列化函数,使用某种_customType属性来标识要调用的适当类名,从而使系统可扩展。 当然,源和目标都必须存在适当的序列化和反序列化扩展才能使其正常工作。

最新更新