了解TypeScript对象序列化

2,944 阅读11分钟

在这篇文章中,我们将了解系统如何通过一个叫做序列化和反序列化的过程进行无缝通信,以及我们如何在TypeScript中应用。这个过程是无缝的,因为可转移的数据是如何处理的。

作为一个用户,当你访问任何应用程序时,你这样做是为了检索信息。这些信息是由必须存储在某处的数据组成的;这就是序列化的作用。

在本文结束时,你应该能够理解数据如何从一个地方传输到另一个地方,以什么格式传输,以及存储数据流的可能选项。我们还将介绍在TypeScript中使用序列化时可能出现的技术问题。

什么是序列化与反序列化?

那么什么是序列化和反序列化?它只是允许数据的无缝传输的过程。

Serialization And Deserialization Diagram, Showing Going From Multidimensional Object To Byte Stream And Back

缓存是序列化和反序列化的一个很好的现实例子,数据被存储在内存中,以便更快地进行检索。

缓存的数据通过网络以序列化的格式传输,存储在内存中,然后,每次请求数据时,它都被反序列化为一个对象。

在这篇文章中,我们还将看一下需要序列化和反序列化过程的不同场景。一般来说,序列化和反序列化过程是在你不知道的情况下发生的。

序列化的意义

序列化主要用于存储一个对象,或者当你想把一个对象从一个活动脚本转移到另一个活动脚本。这种转移可能是从服务器到服务器,服务器到客户端,或者客户端到服务器。

不同的系统必须相互通信,同时接受特定的数据格式。在这种情况下,你要控制序列化和反序列化。串行化消除了接收这些不同数据格式的网关的需要。

一旦序列化完成,字节流可以很容易地在多个平台上共享。然后进行反序列化,将数据重构为原始形式。

串行化和反串行化用例

以下是需要对数据进行序列化和反序列化时的几个不同用例。

HTTP的序列化

HTTP在通过网络浏览器传输数据时使用序列化。例如,一个RESTFul服务有一个HTTP请求,其消息体的内容是一个对象的序列化形式。

会话数据的序列化

会话数据通过通信协议在多个虚拟机之间以序列化的形式传输。

这方面的一个例子是基于会话的认证。当在服务器端以序列化的格式保存用户的信息时,客户端可以向服务器发送请求来检索信息,服务器处理请求然后发回一个反序列化的响应。

Redis的序列化

Redis是一种数据库,使用内存数据集减少应用程序的加载时间。使用序列化,代码转换为一个可持续的数据结构。

视频流

在涉及视频流的应用中,视频被分解成数据包,这是一个以串行方式传输给客户端的字节集合。

序列化和反序列化的好处

除了一般的用例,序列化还提供了许多好处,包括帮助解决通信问题、深度复制和缓存。

例如,通过允许不同的计算机设计同时共享对象,我们可以直接存储任何对象的状态,解决了通信问题。这方面的一个例子是通过网络传输数据,如网络和移动应用。

深度复制的情况下,通过将一个对象序列化为字节数组并反序列化,使克隆过程变得简单而准确。

最后,对于缓存来说,建立一个对象所需的时间要比反序列化一个对象所需的时间多,这意味着序列化通过兑现巨大的对象来节省时间。

在TypeScript中,由于这是一个简单的场景,你可以调用JavaScript函数JSON.stringify ,将一个对象序列化为一个JSON字符串,JSON.parse ,将JSON字符串反序列化为一个对象。下面是一个分别使用JSON.stringifyJSON.parse 的序列化和反序列化Person 对象的例子。

JSON是一种广泛使用的数据格式,因为它以键值对的形式表示数据,它不包括类元数据(对象的类定义,如属性、方法和事件),因为它是结构化数据。

class Person{
 name: string;
 constructor() {
   this.name = 'Serializer';
 }
}

const human = new Person();
Output1: Person { name: 'Serialer' }
const serialized_data = JSON.stringify(human)
Output1:// {"name":"Serializer"}
const deserialized_data = JSON.parse(serialized_data)
Output:// { name: 'Serializer }

查看官方文档,了解更多关于使用JSON.stringify 和的数据类型的不同例子。 JSON.parse.

TypeScript中序列化/反序列化对象时的技术问题

丢失类型信息

看一下上面的Person 类的例子,如果你想把一个JSON对象反序列化成一个类的实例,使用JSON.parse 是不够的。

JSON.parse 方法返回一个普通对象,而不是一个类对象。幸运的是,一些库,如Class-transformer ,可以同时处理TypeScript类的序列化和反序列化而不丢失类型信息。

它允许你使用装饰器将普通对象转化为类对象。查看官方文档,了解更多关于你如何使用它提供的方法轻松地序列化和反序列化一个类

安全地存储序列化的数据

上面的Output1字符串现在可以被传送到其他机器上或被存储起来。为了安全地存储序列化的数据,你可以对数据进行加密。在TypeScript中,你可以使用一个叫做crypto-js 的库来加密序列化的对象。

使用这个工具的要求是要有Node.js和任何node包管理器的安装。在这个例子中,我们将使用nmp。

要安装crypto-js, ,请运行这个命令。

>npm install crypto-js
Usage: 
//Import it in your TS file
const CryptoJS require("crypto-js");
const AES = require("crypto-js/aes");
const serialized_data_encrytedData = CryptoJS.AES.encrypt(
                                    serialized_data,
                                    'my serialized data'
                                  ).toString()

存储数据流的不同方式

我们有不同的方式来序列化对象并存储它们。这样做时要考虑的因素是对可读性的需求、数据的复杂性、速度和空间限制。

这些数据流可以被存储在数据库、内存或文件中。在我们的例子中,我们将使用YAML。

在存储这些数据时,要确保数据的安全性,以避免可能的篡改。安全反序列化的关键因素之一是要知道数据源是什么,而且数据是安全的。

使用YAML文件的优势

YAML是一种数据序列化格式,代表了 "YAML不是标记语言"。

在创建特定领域语言(DSL)时使用YAML是一个额外的优势,因为它的设计是为了提供可读性。YAML文件中的字符串不需要加引号,因此提高了可读性。

由于YAML处理复杂数据类型的特性,使用YAML是小型数据集的理想选择,有助于减少与性能有关的问题。

关于如何在YAML文件中存储数据的一个简单例子是使用js-yaml 模块。要使用这个,你必须安装js-yaml ,并初始化它和文件流。

$ npm install js-yaml
const yaml = require('js-yaml');
const fs   = require('fs');

const object = {
   name: "Serialization",
   category: "db"
}

const serialized_object = JSON.stringify(object);

const yaml_formatted_serialized_object = yaml.dump(serealized_object);

console.log(yaml_formatted_serialized_object);

使用数据库的优点

当以下情况适用于你要序列化或反序列化的那种数据时,数据库是首选。

首先,当你的应用程序的代码不需要不断变化时,使用数据库。例如,一个有人口数据的仪表盘很少需要精确的洞察力。这里的目标是报告数据。

数据只被读取一次,因此性能不是优先考虑的;在这种情况下使用数据库是理想的。

第二,如果不需要在反序列化的数据结构中选择字段,使用数据库是理想的。然而,这样做的缺点是,几乎不可能知道你将来会需要什么类型的查询。

如果你使用LocalStorage datastore作为数据库,你可以通过以下方式实现。

const object = {
 name: "Serialization",
 category: "db"
}
serialized_object = JSON.stringify(object);
// '{"name":"Serialization","category":"db"}'
localStorage.setItem("serialized object", serealized_object)
localStorage.getItem('serialized object')
// '{"name":"Serialization","category":"db"}'
localStorage.setItem("serialized object", serealized_object)

localStorage.getItem('serialized object')

你可以看到,使用JSON.parse() 方法反序列化数据会返回一个普通对象,而不是一个类对象。因此,在序列化类对象时,使用JSON.stringifyJSON.parse 是不够的,因为你会失去类型信息。

幸运的是,一些库,如Class-transformer ,使你能够将普通对象转化为类对象。

在内存中存储数据流的优势

在以下情况下,将序列化的数据存储在内存中是理想的。

首先是当需要实时数据或你需要一个更快的方式来访问数据。例如,在医疗保健行业,立即访问准确的病人信息对潜在的拯救生命至关重要。

当你处理对时间敏感的数据时,将数据流存储在内存中可以使你在瞬间做出决定,就像处理股票交易数据一样,更加容易。你获得数据变化的速度是决定你是赢还是输的关键。

最后,当减少一个应用程序的加载时间时,数据检索的最快方式是将其存储在内存中。例如,Redis使用了一个内存数据集,由于它在存储数据时不使用硬盘,所以检索数据的速度更快

下面是一个如何使用SETGET 命令在Redis中存储序列化数据的例子,假设你已经安装并运行了Redis。

要读取数据,请使用GET 命令。

127.0.0.1:6379>  SET serializedData '{"name":"Serialization","category":"db"}'
output: OK

127.0.0.1:6379> GET serializedData
"{\"name\":\"Serialization\",\"category\":\"db\"}"

序列化和反序列化的优点和缺点

正如我们在这篇文章中所介绍的,序列化和反序列化在许多用例中都非常有用。但是,使用序列化和反序列化的优点和缺点是什么?

序列化和反序列化的优点

因为JavaScript中的简单序列化不需要任何第三方库,而第三方库往往会过时并导致未来的问题,所以它避免了减轻使用外部依赖性所带来的安全相关风险的需要。

序列化和反序列化也不依赖于任何特定的平台。这意味着你可以在一个平台上序列化数据,并在另一个平台上反序列化,当当前许多技术依赖于序列化并需要这种灵活性时,这很有用。

序列化的数据流也支持加密,这导致了一个平稳、更安全的过程。加密你的序列化数据的能力确保了它的安全和更可靠。

串行化和反串行化的缺点

虽然序列化和反序列化有很多好处,但在使用序列化和反序列化时,也有一些缺点需要考虑缓解。

虽然序列化和反序列化是有用的机制,但这个过程很脆弱,可能导致安全问题,而且增加了复杂性,如果使用不当很容易导致安全漏洞。

经验法则是,你写的防御性代码越多,你的应用程序就越安全。

反序列化也会持有分配给对象的所有变量、属性,这使得这个过程变得危险或成为漏洞点。编写针对类的序列化方法很重要,它不会暴露数据流的敏感信息。

确保反序列化过程也不会有任何副作用。

而且,正如我们之前看到的,序列化和反序列化涉及的数据流要求增加应用程序的内存需求。这是由于你的数据流的对象和字符串的所有内存分配的结果,很容易导致内存泄漏。

总结

到目前为止,我们了解到,序列化和反序列化允许对象的可移植性,并通过实例概述了如何存储序列化的数据流。最后,选择如何序列化和反序列化你的数据完全取决于你的应用需求。

学习愉快!

The postUnderstanding TypeScript object serializationappeared first onLogRocket Blog.