序列化

在计算中,序列化(或序列化)是将数据结构对象状态转换为可以存储的格式的过程(例如,辅助存储设备中的文件,主存储设备中的数据缓冲区)或发送(例如,计算机网络上的数据流数据流)并稍后重建(可能在不同的计算机环境中)。当由序列化格式重新阅读所得的位时,它可用于创建原始对象的语义上相同的克隆。对于许多复杂的对象,例如广泛使用参考的对象,此过程并不简单。面向对象的对象的序列化不包括其以前链接的任何相关方法

在某些情况下,序列化对象的这种过程也称为编组对象。相反的操作是从一系列字节中提取数据结构的,是必不可少的,(也称为无序列删除)。

用途

序列化应用程序示例包括:

为了使其中一些功能有用,必须保持建筑独立性。例如,为了最大程度地使用分发,在不同的硬件体系结构上运行的计算机应该能够可靠地重建一个序列化的数据流,而不论endianness如何。这意味着直接复制数据结构内存布局的简单,更快的过程无法可靠地可靠地工作。以独立于架构的格式序列化数据结构意味着防止字节顺序排序,内存布局或仅仅是不同编程语言表示数据结构的不同方式。

任何序列化方案固有的是,因为数据的编码是定义序列的,因此提取序列化数据结构的一个部分要求从头到尾读取整个对象并重建整个对象。在许多应用程序中,这种线性性是一种资产,因为它可以使用简单的,常见的I/O接口来保持和传递对象的状态。在较高性能是问题的应用程序中,花费更多的精力来处理更复杂,非线性存储组织是有意义的。

即使在一台计算机上,原始针对像也太脆弱了,无法保存,因为它们指向的对象可以重新加载到内存中的其他位置。为了解决这个问题,序列化过程包括一个称为“无滚水指针”的步骤,在该步骤中,直接指针参考被基于名称或位置转换为参考。避难所过程包括一个称为指针Swizzling的反向步骤。

由于序列化和应对序列化都可以从通用代码中驱动(例如, Microsoft Foundation类中的序列化函数),因此共同代码可以同时执行两者,因此,1)检测对象之间的差异序列化及其先前的副本,以及2)为下一个此类检测提供输入。没有必要实际构建先前的副本,因为可以即时检测到差异,这是一种称为差分执行的技术。这对于用户界面的编程很有用,其内容具有时间变化 - 可以创建,删除,更改或制作用于处理输入事件的图形对象,而无需一定要编写单独的代码即可完成这些事情。

缺点

序列化通过潜在地揭示私人实施细节来打破抽像数据类型的不透明度。序列化所有数据成员的琐碎实现可能违反封装

为了阻止竞争对手制作兼容产品,专有软件的出版商通常会使他们的程序序列化格式的详细信息成为商业秘密。有些人故意混淆甚至加密序列化数据。但是,互操作性要求应用程序能够理解彼此的序列化格式。因此,远程方法调用架构(例如Corba)详细定义了其序列化格式。

许多机构(例如档案和图书馆)试图通过以一些相对可读的序列化格式将其存储来证明备份档案(尤其是数据库转储)

序列化格式

1980年代初期,施乐网络系统快递技术影响了第一个广泛采用的标准。 Sun Microsystems于1987年发布了外部数据表示(XDR)。XDR是一种开放格式,标准化为STD 67 (RFC 4506)。

在1990年代后期,推动为标准序列化协议提供替代方案的推动力: XMLSGML子集)用于生成基于人类可读的基于文本的编码。这种编码对于人类可能会读取和理解的持久对像或与其他系统通信无关,无论编程语言如何,都可能有用。它的缺点是失去更紧凑的基于字节流的编码,但此时,较大的存储和传输能力使文件大小要比计算初期更少关注。在2000年代,XML通常用于AJAX Web应用程序中客户端和服务器之间结构化数据的异步传输。 XML是一种开放格式,标准化为W3C建议

JSON是XML的轻量级纯文本替代品,也通常用于Web应用程序中的客户端服务器通信。 JSON基于JavaScript语法,但独立于JavaScript,并以许多其他编程语言支持。 JSON是一种开放格式,标准化为STD 90RFC 8259 ), ECMA-404ISO/IEC 21778:2017

YAML是JSON的严格超集集,包括其他功能,例如数据类型标签,对循环数据结构的支持,对压痕敏感的语法以及多种形式的标量数据报价。 YAML是一种开放格式。

属性列表用于NextStepGnustepMacOSiOS框架的序列化。属性列表或简称P-List ,不是指单个序列化格式,而是几种不同的变体,有些人类可读和一个二进制。

对于大容量的科学数据集,例如卫星数据和数值气候,天气或海洋模型的输出,已经开发了特定的二元序列化标准,例如HDFNETCDF和较旧的Grib

编程语言支持

几种面向对象的编程语言直接通过句法糖元素或提供标准接口来支持对象序列化(或对象档案)。这样做的语言包括RubySmalltalkPythonPHPObjective-CDelphiJava.Net语言家族。也有可用的库为缺乏本机支持的语言增加序列化支持。

C和C ++

CC ++不提供任何形式的高级构造,但两种语言都支持编写任何内置数据类型以及普通的旧数据结构,例如二进制数据。因此,编写自定义序列化功能通常是微不足道的。此外,基于编译器的解决方案,例如用于C ++的ODB ORM系统和C ++的GSOAP工具包,能够自动生成序列化代码,几乎没有修改类声明。其他流行的序列化框架是增强框架。从Boost框架,S11N框架和谷物进行了序列化。 MFC框架(Microsoft)还提供序列化方法,作为其文档视图架构的一部分。

CFML

CFML允许将数据结构序列化为WDDX<cfwddx>使用serializejson()函数标记和json

德尔菲

Delphi提供了一种内置机制,用于序列化组件(也称为持久对象),该机制与IDE完全集成在一起。该组件的内容保存到DFM文件并在即时重新加载。

Go anderate支持JSONXML数据的Unarshalling/编组。还有支持YAML协议缓冲区的第三方模块。 GO也支持GOB

哈斯克尔

在Haskell中,对读取类型类的成员的类型支持序列化。每种类型是Read类型类定义一个函数,该函数将从转储数据的字符串表示形式中提取数据。这Show类型类依次包含show可以生成对象的字符串表示形式的函数。程序员无需明确定义函数,而是声明要派生或派生显示的类型,或者两者都可以使编译器在许多情况下生成适当的函数(但不是全部:或阅读)。 SHOW的自动生成实例也会产生有效的源代码,因此可以通过运行Shod In所产生的代码来生成相同的Haskell值,例如Haskell解释器。为了更有效的序列化,有一些Haskell库可以以二进制格式的高速序列化,例如二进制

爪哇

Java提供了自动序列化,该序列化要求对象通过实现java.io.Serializable介面.实现界面将类标记为“可以序列化”,然后Java内部处理序列化。在该方法上没有定义的序列化方法Serializable接口,但是可序列化类可以选择定义具有某些特殊名称和签名的方法,如果定义为定义,将被称为序列化/次要化过程的一部分。该语言还允许开发人员通过实现另一个接口,即更彻底地覆盖序列化过程Externalizable接口,其中包括两种用于保存和还原对象状态的特殊方法。
默认情况下对像不可序列化,必须实现三个主要原因Serializable访问Java序列化机制的接口。
首先,并非所有对像都以序列化状态捕获有用的语义。例如,Thread对象与当前JVM的状态相关。没有任何值得注意的上下文Thread对象将保持有用的语义。
其次,对象的序列化状态构成其类兼容合同的一部分。保持序列化类之间的兼容性需要额外的努力和考虑。因此,使班级序列化需要是故意的设计决定,而不是默认条件。
最后,序列化允许访问其他无法访问的类的非临时私人成员。包含敏感信息的类(例如,密码)不应序列化或外部化。标准编码方法使用对像类描述符和可序列化字段的基于递归图的翻译到字节流中。原语以及非传输,非静态引用的对像被编码到流中。序列化对象通过未标记为序列化对象引用的每个对象transient还必须序列化;而且,如果在非传播对象引用的完整图中的任何对像都不可序列化,则序列化将失败。开发人员可以通过将对象标记为瞬态,或通过重新定义对象的序列化来影响此行为,从而使参考图的某些部分被截断并且不序列化。
Java不使用构造函数来序列化对象。可以通过JDBC序列化Java对象并将其存储到数据库中。虽然摇摆组件确实实现了可序列化的接口,但不能保证它们在Java虚拟机的不同版本之间可移植。因此,可以将摇摆组件或任何继承其继承的组件序列化为字节流,但不能保证这将在另一台计算机上重新定位。

JavaScript

自ecmascript 5.1以来, JavaScript包括内置JSON对象及其方法JSON.parse()JSON.stringify()。尽管JSON最初是基于JavaScript的子集,但在某些边界案例中,JSON没有有效的JavaScript。具体来说,JSON允许Unicode线终止器U+2028行分隔符和U+2029段落分隔符在引用的字符串中显得未散布,而Ecmascript 2018及以上则没有。请参阅有关JSON的主要文章。

朱莉娅

朱莉娅通过serialize()/deserialize()模块,旨在在同一版本的Julia和/或同一系统图像的实例中工作。这HDF5.jl软件包提供了更稳定的替代方案,使用已记录的格式和带有包装器的常见图书馆的不同语言,而默认的序列化格式则是设计的,而不是最大程度地进行网络通信的性能。

Lisp

通常, LISP数据结构可以通过功能序列化”read“ 和 ”print“。(print foo)。同样,可以从名为S的流读取对象(read s)。 LISP实现的这两个部分称为打印机和读者。输出print“人类是可读的;它使用括号符号的列表,例如:(4 2.9 "x" y)。在包括普通LISP在内的许多类型的LISP中,打印机不能表示每种类型的数据,因为尚不清楚如何做。例如,在通用的LISP中,打印机无法打印关闭对象。相反,程序员可以在通用函数上编写方法print-object,当对像打印时将调用此功能。这与Ruby中使用的方法有些相似。 LISP代码本身写在读者的语法中,称为Read语法。大多数语言都使用单独的和不同的解析器来处理代码和数据,LISP仅使用一种。可以将包含LISP代码的文件作为数据结构读取,该数据结构由另一个程序转换,然后可能执行或写出,例如在读取 - eval -print循环中。并非所有读者/作家都支持循环,递归或共享结构。

.NET框架

.NET Framework具有Microsoft设计的几个序列化器。第三方也有许多序列化。 这里讨论和测试了十多个连续剧。和这里

OCAML

Ocaml的标准库通过Marshal模块和Pervasives功能output_valueinput_value。虽然OCAML编程是静态类型检查的,但Marshal模块可以断开类型的保证,因为没有办法检查未绘制的流是否代表预期类型的​​对象。在OCAML中,很难将包含函数的函数或数据结构(例如包含方法的对象)进行元件,因为函数中可执行的代码不能在不同程序中传输。 (有一个标志可以合理函数的代码位置,但只能在完全相同的程序中删除它)。标准编组功能可以保留共享和处理循环数据,可以通过标志配置。

珀尔

CPAN可用的几个PERL模块提供了序列化机制,包括Storable,JSON::XSFreezeThaw。存储包括在文件或perl标量的序列化和序列化perl数据结构的功能。除了直接序列化到文件外,Storable包括freeze函数以返回包装到标量中的数据的序列化副本,然后thaw为了使这样的标量升级。这对于通过网络插座发送复杂的数据结构或将其存储在数据库中很有用。当与Storable,有一些网络安全功能总是以较小的速度成本在任何计算机上可读的格式存储数据。这些功能是命名的nstore,nfreeze等等。thawretrieve与“n“功能及其特定于机器的等效物。

php

PHP最初通过内置实现了序列化serialize()unserialize()功能。 PHP可以序列化其任何数据类型,但资源(文件指针,插座等)都可以序列化。内建unserialize()在完全不信任的数据上使用时功能通常很危险。对于对象,可以在类中实现两个“魔法方法” -__sleep()__wakeup()- 从内部调用serialize()unserialize(),分别可以清理和恢复对象。例如,可能希望在序列化时关闭数据库连接并恢复避难所的连接。此功能将在这两种魔术方法中处理。它们还允许对象选择哪些属性被序列化。自PHP 5.1以来,有一个面向对象的序列化机制,Serializable介面.

序言

Prolog术语结构是语言的唯一数据结构,可以通过内置的谓词序列化write_term/3并通过内置谓词序列化read/1read_term/2。所得流是未压缩的文本(在某些由目标流的配置确定的编码中),术语中的任何自由变量以占位符变量名称表示。谓词write_term/3在第59 ff的Prolog(ISO/IEC 13211-1)的ISO规范中标准化。 (“编写一个术语,第7.10.5节”)。因此,可以预期,通过一个实现序列化的术语可以由另一个实现序列化,而不会歧义或惊喜。实际上,实施特定的扩展(例如Swi-Prog的词典)可能使用非标准的项结构,因此互操作性可能会破坏边缘情况。作为示例,请参见Swi-Progolog,Sicstus Prolog,GNU Prolog的相应手册页。是否以及如何根据规范(从字符流进行避免)将网络接收到的序列化术语被保留给实施者。 Prolog的内置确定子句语法可以在该阶段应用。

Python

核心一般序列化机制是pickle标准库模块,暗示了数据库系统术语腌制,以描述数据序列化(无需挑选)。 Pickle使用基于简单的基于堆栈虚拟机,可记录用于重建对象的指令。它是一种可自定义但不安全(不适合错误或恶意数据的安全)的序列化格式的序列化格式的序列化格式。畸形或恶意构造的数据可能导致避难所导入任意模块并实例化任何对象。标准库还包括序列化标准数据格式的模块:json(具有对基本标量和收集类型的内置支持,并且能够通过编码和解码钩子支持任意类型)。plistlib(支持二进制和XML属性列表格式)。xdrlib(如RFC 1014所述,支持外部数据表示(XDR)标准)。最后,建议对象的__repr__可以在正确的环境中进行评估,使其与普通LISP的粗略匹配print-object。并非所有对像类型都可以自动腌制,尤其是持有文件处理的操作系统资源的对像类型,但是用户可以注册自定义“减少”和施工功能,以支持腌制和未取消任意类型的腌制。 Pickle最初被用作纯Pythonpickle模块,但在3.0之前的Python版本中,cPickle模块(也是内置)提供的性能提高(最多快1000倍)。这cPickle改编自Unladen燕子项目。在Python 3中,用户应始终导入标准版本,该版本试图导入加速版本并落回纯Python版本。

R

r具有功能dput将R对象的ASCII文本表示形式写入文件或连接。可以使用文件从文件中读取表示形式dget。更具体,功能serialize将r对象序列到连接,输出是以十六进制格式编码的原始向量。这unserialize功能允许从连接或原始向量读取对象。

rebol

rebol将序列化到文件(save/all)或string!(mold/all)。字符串和文件可以使用多态性进行重新序列化load功能。RProtoBuf使用协议缓冲区在R中提供跨语言数据序列化。

红宝石

Ruby包括标准模块Marshal使用2种方法dumpload,类似于标准UNIX实用程序dumprestore。这些方法序列到标准类String也就是说,它们有效地成为字节的序列。某些物体不能序列化(这样做会增加TypeError例外):绑定,过程对象,类IO类,单例对象和接口的实例。如果类需要自定义序列化(例如,它需要在倾销 /还原时完成某些清理操作),则可以通过实现2种方法来完成:_dump_load实例方法_dump应该返回一个String对象包含重新构建此类对象的所有信息以及所有引用的对象,最大深度为整数参数(值为-1的值表示应禁用深度检查)。类方法_load应该服用String并返回此类的对象。

Serde是使用最广泛使用的库或板条箱,用于生锈中的序列化。

短暂聊天

通常,可以使用人类可读形式来存储和检索非收集性和非共享对象storeOn:/readFrom:协定.这storeOn:方法生成了Smalltalk表达式的文本readFrom:- 重新创建原始对象。该方案是特殊的,因为它使用对象的程序描述,而不是数据本身。因此,它非常灵活,允许类定义更紧凑的表示。但是,以其原始形式,它不处理环状数据结构或保留共享引用的身份(即两个参考文献将以一个对象恢复为两个相等但不相同的副本的引用)。为此,存在各种便携式和不可存储的替代方案。其中一些是特定于特定的SmallTalk实现或班级库。 Squeak Smalltalk有几种序列化和存储对象的方法。最简单,最常用的是storeOn:/readFrom:和基于二进制存储格式SmartRefStream连续化器。此外,捆绑的对象可以使用ImageSegments。两者都提供了所谓的“二进制目标存储框架”,该框架支持从紧凑的二进制形式中序列化并检索。都处理循环,递归和共享结构,类别的存储/检索以及元素信息,并包含“ fly”对象迁移的机制(即转换由具有不同对象布局的类较旧版本编写的实例)。 API是相似的(StoreBinary/Readbinary),但是编码细节不同,这两种格式不兼容。但是,SmallTalk/X代码是开源的,可以免费加载到其他SmallTalks中,以允许跨二级对象互换。对象序列化不是ANSI SmallTalk规范的一部分。结果,序列化对象的代码因SmallTalk实现而异。产生的二进制数据也有所不同。例如,在Ambrai Smalltalk中无法恢复在Spreatsmalltalk中创建的序列化对象。因此,在依赖对象序列化的多个SmallTalk实现的各种应用程序都无法共享这些不同的实现之间的数据。这些应用程序包括Minnestore对像数据库和一些RPC软件包。解决此问题的解决方案是六X,它是用于使用基于XML的格式进行序列化的多个SmallTalks的包装。

迅速

Swift Standard库提供了两个协议,EncodableDecodable(组成为Codable),允许将符合类型的实例序列化为JSON属性列表或其他格式。编译器可以生成这些协议的默认实现,以生成其存储属性的类型Decodable或者Encodable.

Windows PowerShell

Windows Powershell通过内置CMDLET实现序列化Export-CliXML.Export-CliXML序列化.NET对象并将结果XML存储在文件中。要重建对象,请使用Import-CliXMLcmdlet,从导出的文件中的XML生成一个值得序列化的对象。供应对象(通常称为“财产袋”)不是活物体;它们是具有属性但没有方法的快照。还可以使用内置的CMDLET以CSV格式序列化二维数据结构Import-CSVExport-CSV.

也可以看看