-
Notifications
You must be signed in to change notification settings - Fork 88
Hprose 序列化
Hprose 提供了一套自己的序列化格式用来实现高效的跨语言跨平台的数据存储和交换。该序列化格式,在 hprose for Node.js 中被实现为以下几个对象:
- hprose.Tags
- hprose.ClassManager
- hprose.Writer
- hprose.Reader
- hprose.Formatter
其中 hprose.Tags
对象中包含了所有的 Hprose 序列化和 RPC 标记定义。Hprose 的使用者通常不需要关心该对象,因此这里不对该对象做详细介绍。
hprose.ClassManager
用于管理自定义类型与其它语言之间的映射关系。
hprose.Writer
用于进行细粒度的 Hprose 序列化操作。
hprose.Reader
用于进行细粒度的 Hprose 反序列化操作。
hprose.Formatter
用于进行粗粒度的 Hprose 序列化和反序列化操作。
另外,hprose
对象上也提供了三个帮助方法,用于注册自定义类型(register
),序列化(serialize
)和反序列化(unserialize
)数据。下面我们将对这几个对象和方法进行详细的介绍。
hprose.ClassManager.register(class, alias);
在 javascript 中,是没有类的概念的,这里的类是指对象的构造器函数。
当 hprose 序列化对象时,需要知道对象的类名,但有时候,对象的构造器函数可能是个匿名函数,并没有函数名。或者我们在不同的语言中定义的类名可能不同,但结构相同或相近,我们希望这些定义不同的类的对象可以相互传递。那么就需要使用该方法来进行注册,注册成统一的别名之后,就可以相互传递了。
其中 class
表示要注册的类(对象的构造器函数),alias
表示注册的别名。例如:
var User = function() {
this.name = 'Tom';
this.age = 18;
}
hprose.ClassManager.register(User, 'User');
在有些语言中,类名是有名称空间(NameSpace)的,例如在 java 中,可能有这样一个类:my.package.User,我们希望它能跟这里的 User 进行交互,那我们应该这样做:
hprose.ClassManager.register(User, 'my_package_User');
注意上面的别名中,不是使用 .
做分隔符的,而是使用 _
,hprose 之所以这样做是因为有些语言不支持名称空间(NameSpace),还有些语言的名称空间(NameSpace)和类名之间不是使用 .
分隔符的,因此这里统一成 _
,这样既可以支持没有名称空间(NameSpace)的语言,也可以支持具有名称空间(NameSpace)的语言。
因为该方法比较常用,所以 hprose 还提供了一个简单的写法:
hprose.register(User, 'my_package_User');
hprose.ClassManager.getClassAlias(class);
通过类来查找别名,例如:
hprose.register(User, 'my_package_User');
console.log(hprose.ClassManager.getClassAlias(User));
输出结果为:
my_package_User
hprose.ClassManager.getClass(alias);
通过别名来查找注册的类。例如:
var User = hprose.ClassManager.getClass('my_package_User');
var writer = new hprose.Writer(stream[, simple]);
第一个参数 stream
是一个 BytesIO
的实例对象,序列化数据将会写入到该对象中。
第二个参数 simple
如果为 true
,则不使用引用方式序列化,通常在序列化的数据中不包含引用类型数据时,设置为 true
可以加快速度。当包含引用类型数据时,需要设置为 false
(即默认值),尤其是当引用数据中包括递归数据时,如果不使用引用方式,会陷入死循环导致堆栈溢出的错误。
只读属性,返回当前用于写入序列化数据的 BytesIO
实例对象。该属性的值即上面构造器中的第一个参数。
writer.serialize(value);
序列化数据 value
。其中 value
为任意 hprose 支持的类型。
writer.writerInteger(value);
序列化一个整数 value
。其中 value
为一个 32 位有符号整型数。超过这个范围的整数按照长整型数格式序列化。
writer.writeDouble(value);
序列化一个浮点数 value
。
writer.writeBoolean(value);
序列化一个布尔值 value
。
writer.writeUTCDate(value);
序列化一个 UTC 日期时间值 value
。其中 value
为 Date
类型的实例对象。
writer.writeUTCDateWithRef(value);
序列化一个 UTC 日期时间值 value
,如果该值之前被序列化过,则作为引用序列化。
writer.writeDate(value);
序列化一个本地日期时间值 value
。其中 value
为 Date
类型的实例对象。
writer.writeDateWithRef(value);
序列化一个本地日期时间值 value
,如果该值之前被序列化过,则作为引用序列化。
writer.writeTime(value);
序列化一个本地时间值 value
。其中 value
为 Date
类型的实例对象。
writer.writeTimeWithRef(value);
序列化一个本地时间值 value
,如果该值之前被序列化过,则作为引用序列化。
writer.writeBytes(value);
序列化一个二进制数据值 value
。其中 value
为 ArrayBuffer
、Uint8Array
、BytesIO
、Buffer
类型的实例对象或是元素是纯整数且数字范围是 0-255 的普通数组。
writer.writeBytesWithRef(value);
序列化一个二进制数据值 value
,如果该值之前被序列化过,则作为引用序列化。
writer.writeString(value);
序列化一个字符串值 value
。
writer.writeStringWithRef(value);
序列化一个字符串值 value
,如果该值之前被序列化过,则作为引用序列化。
writer.writeList(value);
序列化一个 List 值 value
。其中 value
是一个普通数组或者 TypedArray 类型的实例对象。
注意:对 Uint8Array 类型的实例对象使用 writeBytes 会更加高效。
writer.writeListWithRef(value);
序列化一个 List 值 value
,如果该值之前被序列化过,则作为引用序列化。
writer.writeMap(value);
序列化一个 Map 值 value
。其中 value
是一个普通的 javascript 对象(比如直接使用 JSON 形式创建的对象)或 ECMAScript 6 的 Map 对象。
writer.writeMapWithRef(value);
序列化一个 Map 值 value
,如果该值之前被序列化过,则作为引用序列化。
writer.writeObject(value);
序列化一个对象值 value
。其中 value
是一个对象。该对象的构造器已经通过 hprose.ClassManager.register
方法注册,或者该对象的构造器是一个非匿名函数。
writer.writeObjectWithRef(value);
序列化一个对象值 value
,如果该值之前被序列化过,则作为引用序列化。
writer.reset();
将序列化的引用计数器重置。
var reader = new hprose.Reader(stream[, simple[, useHarmonyMap]]);
第一个参数 stream
是一个 BytesIO
的实例对象,反序列化数据将会从该对象中读取。
第二个参数 simple
如果为 true
,则不使用引用方式反序列化,通常在反序列化的数据中不包含引用类型数据时,设置为 true
可以加快速度。当包含引用类型数据时,需要设置为 false
(即默认值),否则会抛出异常。
第三个参数 useHarmonyMap
如果为 true
,则反序列化 Map 时,会以 ECMAScript 6 中的 Map 类型的实例对象返回反序列化值。否则返回 Object 对象。当反序列化的 Map 的键(key)为非字符串以外的其它类型(或多种混合类型)时,将该参数设置为 true
可以得到更准确的反序列化结果。默认值为 false
。
只读属性,返回当前用于读取反序列化数据的 BytesIO
实例对象。该属性的值即上面构造器中的第一个参数。
功能同上面的第三个参数一样,可以在对象创建之后进行设置。
reader.checkTag(expectTag[, tag]);
如果第二个参数不存在,则自动读取当前流中的一个字节作为 tag
值。如果 expectTag
和 tag
不一致,则抛出异常。
该方法没有返回值。
reader.checkTags(expectTags[, tag]);
如果第二个参数不存在,则自动读取当前流中的一个字节作为 tag
值。如果 expectTags
中不包含 tag
,则抛出异常。
expectTags
是一个数组,该数组中包含一个或多个 hprose.Tags 中的枚举值,当然也可以是其它 0-255 的任意整数,但通常不会用其它取值。
如果该方法执行成功,返回 tag
值。
reader.unserialize();
从当前数据流中读取数据并返回反序列化结果。如果当前数据流中包含有多个序列化数据,则一次只返回一个结果。
如果反序列化过程中发生错误,则会抛出异常。
reader.readInteger();
从当前数据流中反序列化一个整数结果并返回。
如果反序列化过程中发生错误,则会抛出异常。
reader.readLong();
从当前数据流中反序列化一个长整数结果并返回,如果该结果超出 JavaScript 可表示的整数范围,则以字符串形式返回结果。
如果反序列化过程中发生错误,则会抛出异常。
reader.readDouble();
从当前数据流中反序列化一个浮点数结果并返回。
如果反序列化过程中发生错误,则会抛出异常。
reader.readBoolean();
从当前数据流中反序列化一个布尔值结果并返回。
如果反序列化过程中发生错误,则会抛出异常。
reader.readDate();
从当前数据流中反序列化一个 Date 结果并返回。
如果反序列化过程中发生错误,则会抛出异常。
reader.readDateWithoutTag();
从当前数据流中反序列化一个 Date 结果并返回,该方法假设序列化标记已被读取,并且其值为 hprose.Tags.TagDate。
如果反序列化过程中发生错误,则会抛出异常。
reader.readTime();
从当前数据流中反序列化一个只包含时间的 Date 结果并返回。
如果反序列化过程中发生错误,则会抛出异常。
reader.readTimeWithoutTag();
从当前数据流中反序列化一个只包含时间的 Date 结果并返回,该方法假设序列化标记已被读取,并且其值为 hprose.Tags.TagTime。
如果反序列化过程中发生错误,则会抛出异常。
reader.readBytes();
从当前数据流中反序列化一个二进制数据结果并返回。返回结果为 Uint8Array
类型的实例对象。
如果反序列化过程中发生错误,则会抛出异常。
reader.readBytesWithoutTag();
从当前数据流中反序列化一个二进制数据结果并返回。该方法假设序列化标记已被读取,并且其值为 hprose.Tags.TagBytes。
如果反序列化过程中发生错误,则会抛出异常。
reader.readString();
从当前数据流中反序列化一个字符串结果并返回。
如果反序列化过程中发生错误,则会抛出异常。
reader.readStringWithoutTag();
从当前数据流中反序列化一个字符串结果并返回。该方法假设序列化标记已被读取,并且其值为 hprose.Tags.TagString。
如果反序列化过程中发生错误,则会抛出异常。
reader.readGuid();
从当前数据流中反序列化一个 GUID 结果并返回,结果为字符串类型。
如果反序列化过程中发生错误,则会抛出异常。
reader.readGuidWithoutTag();
从当前数据流中反序列化一个 GUID 结果并返回。该方法假设序列化标记已被读取,并且其值为 hprose.Tags.TagGuid。
如果反序列化过程中发生错误,则会抛出异常。
reader.readList();
从当前数据流中反序列化一个 List 结果并返回,结果为数组类型。
如果反序列化过程中发生错误,则会抛出异常。
reader.readListWithoutTag();
从当前数据流中反序列化一个 List 结果并返回。该方法假设序列化标记已被读取,并且其值为 hprose.Tags.TagList。
如果反序列化过程中发生错误,则会抛出异常。
reader.readMap();
从当前数据流中反序列化一个 Map 结果并返回,结果为 Object 类型的实例对象或 ECMAScript 6 的 Map 类型的实例对象。
如果反序列化过程中发生错误,则会抛出异常。
reader.readMapWithoutTag();
从当前数据流中反序列化一个 Map 结果并返回。该方法假设序列化标记已被读取,并且其值为 hprose.Tags.TagMap。
如果反序列化过程中发生错误,则会抛出异常。
reader.readObject();
从当前数据流中反序列化一个对象结果并返回。该对象的构造器会通过以下方式查找或生成:
如果已经通过 hprose.ClassManager.register
方法注册,并可以查找到,直接返回。
如果在全局通过遍历搜索可以查找到同名构造器,则自动注册,并返回。
通过将读取到的类名中的 _
分别替换成 .
来全局遍历查找同名构造器,如果找到,则自动注册,并返回。
如果通过以上方式都查找不到,则自动生成一个构造器,然后自动注册,并返回。
自动生成的构造器上会添加一个 getClassName 方法,该方法会返回反序列化时读取到的类名。
如果反序列化过程中发生错误,则会抛出异常。
reader.readObjectWithoutTag();
从当前数据流中反序列化一个对象结果并返回。该方法假设序列化标记已被读取,并且其值为 hprose.Tags.TagObject。
如果反序列化过程中发生错误,则会抛出异常。
reader.reset();
将反序列化的引用计数器重置。
hprose.Formatter.serialize(value[, simple]);
该方法会将 value
进行序列化并返回序列化后的数据。如果 simple
为 true
,则不使用引用方式序列化,通常在序列化的数据 value
中不包含引用类型数据时,设置为 true
可以加快速度。当包含引用类型数据时,需要设置为 false
(即默认值),尤其是当引用数据中包括递归数据时,如果不使用引用方式,会陷入死循环导致堆栈溢出的错误。
返回结果为 Uint8Array 类型的对象实例。
如果序列化过程中发生错误,则会抛出异常。
hprose 还提供了一个简化写法:
hprose.serialize(value[, simple]);
注意:该简化写法跟完整写法返回值类型不同,简化写法的返回值为 BytesIO 类型的对象实例。
hprose.Formatter.unserialize(stream[, simple[, useHarmonyMap]]);
从数据流 stream
中读取数据并返回反序列化结果。如果当前数据流中包含有多个序列化数据,则一次只返回一个结果。
stream
为反序列化的数据来源,它可以是一个 BytesIO
对象,也可以是一个 ArrayBuffer
、Uint8Array
或 Buffer
对象。
第二个参数 simple
如果为 true
,则不使用引用方式反序列化,通常在反序列化的数据中不包含引用类型数据时,设置为 true
可以加快速度。当包含引用类型数据时,需要设置为 false
(即默认值),否则会抛出异常。
第三个参数 useHarmonyMap
如果为 true
,则反序列化 Map 时,会以 ECMAScript 6 中的 Map 类型的实例对象返回反序列化值。否则返回 Object 对象。当反序列化的 Map 的键(key)为非字符串以外的其它类型(或多种混合类型)时,将该参数设置为 true
可以得到更准确的反序列化结果。默认值为 false
。
如果反序列化过程中发生错误,则会抛出异常。
hprose 还提供了一个简化写法:
hprose.unserialize(stream[, simple[, useHarmonyMap]]);
该简化写法跟完整写法在功能上没有任何区别。