JavaScript中解析序列化和反序列化

102 阅读3分钟

简单来讲,序列化是指将JS对象转化为一系列的字节的过程,这些字节可以被存储到文件,数据库,或者通过网络传输。反过来,反序列化是指将这些字节重新转换为JS对象的过程。 比如我们将用户的对象,比如姓名年龄,如果想将这个存储起来或者传输给服务器,我们就必须先序列化它,等到需要使用的时候,在通过反序列化将其恢复成原来的对象。

为什么需要序列化?

之所以需要序列化直白的讲是为了实现持久化存储和网络传输,尤其在分布式系统中,不同的机器需要交换对象数据,序列化就是实现这一点的关键。同时,redux等状态容器依赖序列化实现快照和时间旅行调试。此外序列化也可以帮助我们实现深拷贝,创建对象的副本。实例对象是应用层的,不同的语言创建的对象还不一样,实现持久化和网络传输的载体不认识它们。

-如何实现序列化和反序列化?

方案1:API

  1. JSON.stringify()方法对象解析,以字符串形式存储对象结构

方法: JSON.stringify(value, replacer, space) value:需要处理的值,对象或者数组 replacer:可选,为函数表明序列化过程中,序列化值均需要经过它的处理,若为数组,表示只有包含在这个数组中的属性名才会被序列化最后的JSON字符串中,为null或者未传递,value均进行序列化 space:可选参数,缩进用的空白字符串,美观

方案2: toJSON()方法

如果一个被序列化的对象拥有toJSON()函数,那么toJSON()函数就会覆盖默认的序列化行 toJSON: function(){ Name: this.name; } 通过闭包实现的

方案3:serialijse持久性框架

解决了API的两个问题,一个是循环引用的问题,并且在反序列化的时候保留了对象类。可以在node.js或者浏览器中使用,这样就可以在整个网络上传输数据,并且在客户端创建与服务端上相同的对象模型。

反序列化

方案1: JSON.parse(text, reviver)

text: 待解析的JSON字符串 reviver: 可选,若为函数,则规定了原始值在返回前如何被解析改造。如果解析非法的,抛出异常

方案2: eval()

eval()函数用于计算JavaScript字符串,并把它作为脚本来执行。 eval("(" + str + ")") 因为JSON字符串是以“{}”表示开始和结束,在JavaScript中它会被当作一个语句块来处理,所以必须强制将它处理成一个表达式,所以采用括号。

会有什么问题?

  1. 循环引用 解决: ES6中,引入了弱引用WeakSet,也就是说当没有其他强引用指向它时,可以被浏览器内存回收。 const cache = new WeakSet()
  2. 安全方面 恶意JSON注入, 原型污染,允许动态修改对象属性的前提下,通过JSON注入_proto_属性,例如"proto":{"isAdmin":true} 解决:显示过滤,使用Object.hasOwnProperty 特殊字符导致解析异常:字符串中插入空字符)/u0000干扰数据库存储因为后端会进行截断空字符后内容

XSS漏洞,在JSON插入一个

解决: 内容安全策略

避免使用eval()

在实际项目中可以结合JSON Scheme验证,压缩算法构建高性能高可靠的数据交互系统