简介

序列化是指将内存中的对象持久化。比如讲对象保存到磁盘。反过来从二进制流恢复到内存称为反序列化。 序列化技术也广泛用于网络传输(如 RPC)、多进程通信。

序列化离我们并不遥远, 日常开发过程中,很多时候我们意识不到自己正在使用序列化,甚至在创建序列化协议。

日常序列化

这是一个常见的例子。

我们要保存一批语料,每一条有三个字段: 领域、句子、分类。 最先想到的大概就是使用逗号分隔字段, 保存到文件中。

corpus.txt:

金融,昨天上证指数又跌了,1
计算机,PHP是世界上最好的语言,0
科技,GPT-3消耗资源很多,2

然后,把这个文本交给业务方用, 一切都很顺利。 在这个场景中, 涉及到一些概念。

我们自定义了专用的序列化协议

尽管这个协议很简单,而且很不完美,但是它能满足业务需求。

这个序列化协议不是 schema-less 的

这份数据本身并不带有格式,要知道每个字段含义,必须提供 领域、句子、分类 这个 schema 才知道具体怎么解释语料。

而这个 schema 也是不明确的,比如没有明确说明 第三个字段是 int 类型还是 string 类型。 只能靠人观察。

困境

方案的缺陷: 当……

句子中有逗号

这是很明显的缺陷,也有很多种解决方法。

  1. 调整字段的顺序,把长文本类放在最后: 其他,3,我喜欢苹果,还喜欢西瓜

    这是一种规避方案,固定解释前两个无歧义字段,剩下的都当作文本处理。

  2. 引入斜杠转义逗号: \, , 感觉没几个人有这耐性…… , 因为这意味着你还要继续实现转义斜杠: \\ ,还有预料不到的歧义逻辑。

  3. 使用 CSV。 嗯…… 反正都是逗号分隔。

    坏处就是,你要找一个csv解析库, 顺便学一学它的用法。

  4. 使用 json。

句子中有换行

这个问题, 使用 csv 也解决不了, 建议用 json 或者 Excel。

schema-less

你幸苦制作了一批语料,两个月之后, 因为记不起schema而不知道怎么使用,这是一件很恼火的事情。

csv 数据某种程度上说是自描述 (schema-less) 的, 可以通过表头表示每一列的含义,问题是 csv 的表头并不是强制的。

所以,这里我还是推荐使用 JSON:

  1. schema-less 。
  2. 可以表示复杂数据,如 list-map 之间相互嵌套。
  3. 具有类型的概念。如 string、number、bool、null

如何解决

我还是推荐 json , 对 nlp 来说,它够用了, 而且 json 是最容易使用和 debug 的无歧义序列化方案。

但要bb一句: 在其他领域,json 通常并不是好的选择。 真正的生产环境的(非文本)序列化场景,有很多其他(二进制)序列化框架可供选择。

序列化框架

选择序列化框架的时候,有几个指标可以考虑。

  1. 是否人可阅读。即文本还是二进制类型的序列化。
  2. 解码速度
  3. 编码速度
  4. 数据编码后大小。这对网络IO有影响。

有很多网上的性能评测可以参考, 只不过把它们用在自己的业务场景性能如何就是另外一回事了,不能尽信。

根据 数据种类、要求的特性、传输方式、server/client性能 的不同, 对序列化框架的选择也有很大影响。

本章节是入门教程,主要介绍各个序列化框架的内部实现。 以便在编码过程中对序列化框架做出正确的选择。