关于序列化和反序列化是一个老生常谈的问题,在这里概述一下较为容易理解的内容。
备注:红色为重点
一、定义以及相关概念
- 基于OSI七层协议模型:
互联网的产生带来了机器间通讯的需求,而互联通讯的双方需要采用约定的协议,序列化和反序列化属于通讯协议的一部分。通讯协议往往采用分层模型,不同模型每层的功能定义以及颗粒度不同,例如:TCP/IP协议是一个四层协议,而OSI模型却是七层协议模型。在OSI七层协议模型中展现层(Presentation Layer)的主要功能是把应用层的对象转换成一段连续的二进制串,或者反过来,把二进制串转换成应用层的对象--这两个功能就是序列化和反序列化。一般而言,TCP/IP协议的应用层对应与OSI七层协议模型的应用层,展示层和会话层,所以序列化协议属于TCP/IP协议应用层的一部分。
- 序列化: 将数据结构或对象转换成二进制串的过程
- 反序列化:将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程
2.另一种说法:
序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
二、序列化协议特性(部分)
可调试性/可读性
序列化和反序列化的数据正确性和业务正确性的调试往往需要很长的时间,良好的调试机制会大大提高开发效率。序列化后的二进制串往往不具备人眼可读性,为了验证序列化结果的正确性,写入方不得同时撰写反序列化程序,或提供一个查询平台--这比较费时;另一方面,如果读取方未能成功实现反序列化,这将给问题查找带来了很大的挑战--难以定位是由于自身的反序列化程序的bug所导致还是由于写入方序列化后的错误数据所导致。对于跨公司间的调试,由于以下原因,问题会显得更严重:
第一、支持不到位,跨公司调试在问题出现后可能得不到及时的支持,这大大延长了调试周期。
第二、访问限制,调试阶段的查询平台未必对外公开,这增加了读取方的验证难度。
如果序列化后的数据人眼可读,这将大大提高调试效率, XML和JSON就具有人眼可读的优点。
性能
性能包括两个方面,时间复杂度和空间复杂度:
第一、空间开销(Verbosity), 序列化需要在原有的数据上加上描述字段,以为反序列化解析之用。如果序列化过程引入的额外开销过高,可能会导致过大的网络,磁盘等各方面的压力。对于海量分布式存储系统,数据量往往以TB为单位,巨大的的额外空间开销意味着高昂的成本。
第二、时间开销(Complexity),复杂的序列化协议会导致较长的解析时间,这可能会使得序列化和反序列化阶段成为整个系统的瓶颈。
三、几种常见的序列化和反序列化协议
当下比较流行的序列化协议,包括XML、JSON、Protobuf、Thrift和Avro。
关于上面的几种协议的相关知识可用在文章末尾的参考文章中学习或通过其他途径进行学习。
四、问答
Q:为什么一会儿说序列化是将将数据结构或对象转换成二进制串的过程,一会儿又说序列化是将对象的状态信息转换为可以存储或传输的形式的过程?
A:其实,进行序列化的目的是为了跨机器,跨语言进行数据传输,最后还可能进行存储,而且被序列化后的数据结构或对象是否具有人眼可读可读性也是一个方面。在C#中,主要有BinaryFormatter、SoapFormatter、XmlSerializer以及Newtonsoft.Json中的JsonConvert这几种类型提供序列化功能。例如BinaryFormatter是将数据结构或对象序列化为二进制串(byte[]),不具备人眼可读性,数据正确性和业务正确性的调试往往需要很长的时间。相反如果将数据结构或对象序列化为Xml或Json,既满足了需求,又提升了可读性。
Q:该怎样选择序列化协议?
A:根据具体需求以及解析性能、空间开销等进行选择。例如:
JSON在很多应用场景中可以替代XML,更简洁并且解析速度更快。典型应用场景包括:
1、公司之间传输数据量相对小,实时性要求相对低(例如秒级别)的服务。
2、基于Web browser的Ajax请求。
3、由于JSON具有非常强的前后兼容性,对于接口经常发生变化,并对可调式性要求高的场景,例如Mobile app与服务端的通讯。
4、由于JSON的典型应用场景是JSON+HTTP,适合跨防火墙访问。
参考:http://kb.cnblogs.com/page/515982/