如何序列化和反序列化 JavaScript 对象?
Posted
技术标签:
【中文标题】如何序列化和反序列化 JavaScript 对象?【英文标题】:How to serialize & deserialize JavaScript objects? 【发布时间】:2011-04-06 05:33:07 【问题描述】:我需要序列化和反序列化 javascript 对象以将它们存储在数据库中。
请注意,这些对象包含函数,所以我不能将它们存储为 JSON,所以我不能使用 json2.js。
JavaScript 对象的[反]序列化(当然是在 JavaScript 中)的最新技术是什么。
【问题讨论】:
如果 javascript 对象包含函数(即:方法),则无法在 JSON 中对它们进行编码。 JSON 只处理带有纯数据(散列、数组和原始类型)的 JS 对象。 具体来说:我需要存储来自 Google Maps Javascript API 的 DirectionsResult 对象。 DirectionsResult 包含 LatLng 对象,这些对象具有 JSON 无法处理的功能:code.google.com/apis/maps/documentation/javascript/… 我们不能将函数对象作为字符串存储在 json 中吗?? 我想序列化包含字符串的对象以通过 html 传递它们,允许所有字符。 JSON 禁止控制字符。我不需要序列化函数。有什么简短的功能吗? 【参考方案1】:使用 gserializer:
http://www.onegeek.com.au/articles/programming/javascript-serialization.php
google 中的代码:
http://code.google.com/p/gserializer/
GSerializer 是一个 JavaScript 库,用于 序列化/反序列化 javascript 对象往返于字符串,对于 比如说,一个 Cookie 的持久性。不像 许多其他实现, GSerializer 也可以序列化 函数和非 JSON 表示法。
【讨论】:
我早些时候遇到过,但我不确定该项目的成熟度。你个人用过吗? 看起来它不起作用:Gserializer TODO 说:“实现将参数传递到序列化函数(目前仅支持无参数函数)”,并且我必须序列化的对象包含函数参数(LatLng 对象上的 toUrlValue 函数:code.google.com/apis/maps/documentation/javascript/…)。还是谢谢! 对不起2,我希望他们完成这个项目 他已经一年没碰这个项目了。太糟糕了。我还需要带参数的函数【参考方案2】:一般来说,(在浏览器中)无法序列化带有附加函数的对象:每个函数都有对其外部作用域的引用,当您反序列化它时该作用域将不存在,因此对该作用域的序列化引用将无效。
我要做的是使用带有replacer
和reviver
参数的内置(或json2.js)JSON.stringify
和JSON.parse
函数。这是它如何工作的部分示例:
JSON.stringify(yourObject, function(name, value)
if (value instanceof LatLng) // Could also check the name if you want
return 'LatLng(' + value.lat() + ',' + value.lng() + ')';
else if (...)
// Some other type that needs custom serialization
else
return value;
);
JSON.parse(jsonString, function(name, value)
if (/^LatLng\(/.test(value)) // Checking the name would be safer
var match = /LatLng\(([^,]+),([^,]+)\)/.exec(value);
return new LatLng(match[1], match[2]);
else if (...)
...
else
return value;
);
您可以在自定义类型中使用任何您想要的序列化格式。 “LatLng(纬度,经度)”格式只是其中一种方式。您甚至可以返回一个可以原生序列化为 JSON 的 JavaScript 对象。
【讨论】:
有趣。我阅读了 json2.js 文档(“排除了在 JSON 中没有表示的值(例如函数和未定义)。”)并假设没有在函数上调用替换器/恢复器函数。这段代码是你实际编写和使用的吗? @Stewart:这个想法是,当您反序列化它们时,您可以通过重新构造对象来避免序列化函数。LatLng
构造函数将为您重新添加函数。替换器将在函数上工作,所以如果你真的想要,你可以尝试将函数转换为字符串。请注意,它并非在所有情况下都有效。
不处理字符串中的某些字符,例如换行符。【参考方案3】:
你不想序列化诸如函数之类的逻辑。
如果您将来必须更新您的逻辑/js 函数,您不(总是)希望旧的逻辑必须与数据一起加载。小心。
【讨论】:
【参考方案4】:在 Node.js 上,还有 JASON package。
示例如下:
var JASON = require("JASON");
str = JASON.stringify(obj);
obj = JASON.parse(str);
通过npm install JASON
安装包。
【讨论】:
【参考方案5】:出于安全原因,我不会序列化 JS 函数。通过公共 API 可以将各种讨厌的东西发送到数据库。至于反序列化,我有不同的方法。我正在将客户端定义的模型对象与来自 JSON 的数据混合。我有一个小工具可以做到这一点,在 GitHub 上查看它khayll/jsonmix。
JsonMix 提供了一种从 JSON 反序列化为带有函数的 JavaScript 对象。
它看起来像:
//model definition (just an example)
var LatLng = function()
LatLng.prototype.getMapTypeId = function()
return this.mapTypeId;
//deserializing done like this
var result = JSMix(jsonString).withObject(LatLng.prototype, "latLngs").build();
//all items in the latLngs collection have the functions coming from the model
console.log(result.latLngs[5].getMapTypeId());
【讨论】:
您能否解释一下为什么 序列化 Javascript 函数在任何情况下都可能存在安全风险? 如果您有一个公共 API,它接受包括功能在内的序列化 javascript 对象,并且在 Web 应用程序中使用。然后可以将恶意代码发送到您的服务器。假设您还在 Web 应用程序的某处读回这些对象并使用它们。现在,如果有人重写了该对象上的 toString() 函数,而您碰巧在代码中使用了它,那么有人可能会更改 Web 应用程序的预期功能。因此,当您从安全 URL 下载它时,该功能将不再受信任。 当然。但风险在于服务器的接受以及随后的反序列化和代码使用。序列化本身并不危险。 @fishgen Code Bling 是对的。更重要的是,没有必要假设他的用例或序列化的预期目的是你的。例如,他的目的可能是出于合规目的进行归档;以研究为导向;或任何数量的其他目的。【参考方案6】:如果您使用的是 ES6 版本的 Node,您可以查看我编写的一个名为 JSOFF 的小包。它是 JavaScript 对象函数格式;处理函数的 JSON 的直接替代品。
它超级小而且简单,所以 Babeljs 或 Browserify 可能是你的朋友。
通过以下方式安装:npm install jsoff
或 yarn add jsoff
。
以下是如何使用函数创建对象的示例:
const JSOFF = require('jsoff');
var obj =
abc: 123,
def: function (a,b) return a * 2 + b * 3; ,
ghi: a => return a * 2 ,
jkl: (a,b) => return ((d,e) => return a*d + b*e )(2,4)
;
var str = JSOFF.stringify(obj);
// str is now:
// '"abc":123,"def":"function (a,b) return a * 2 + b * 3; ","ghi":"a => return a * 2 ","jkl":"(a,b) => return ((d,e) => return a*d + b*e )(2,4) "');
);
var clone = JSOFF.parse(str);
clone.def(10,5) // 35
clone.ghi(5) // 10
clone.jkl(10,20) // 100
【讨论】:
以上是关于如何序列化和反序列化 JavaScript 对象?的主要内容,如果未能解决你的问题,请参考以下文章