深入Atlas系列:探究序列化与反序列化能力(下) - JavaScriptSerializer
2006-11-10 00:39:11
版权声明:原创作品,如需转载,请与作者联系。否则将追究法律责任。 | |||||||||||||||||||||||||||||||||
在ASP.NET
AJAX中,客户端的序列化与反序列能力由Sys.Serialization.JavaScriptSerializer类的serialize和
deserialize两个静态方法提供。在服务器端,所有的序列化与反序列化能力,包括类型之间的转换,对于开发人员来说都是由
JavaScriptSerializer类的几个方法实现的。从前一片文章里我们已经知道了两个辅助的类:
JavaScriptTypeResolver和JavaScriptConverter,他们的作用分别是“映射类与类标识”,以及“提供特定类的序列
化与反序列化能力”。在以后的文章里,我将通过两个示例来演示这两个类在Web Services Access中直接或者间接的使用方式。 在某些情况下,我们还是需要使用JavaScriptSerializer类的方法来操作一个类型,例如使用JavaScriptConverter来 自定义特定类的序列化或者反序列化,就需要使用JavaScriptSerializer类的方法,因此我们这次就详细看一下这个类的能力。 在JavaScriptSerializer中,我们可以看到下面可以使用的方法或者构造函数,它们都是实例方法:
在这里我们主要来看一下ConvertToType,Deserialize,DeserializeObject和Serialize的两个重载方法。 1、ConvertToType<T>(Object) ConvertToType<T>(Object)方法的作用是将一个Object对象转换为指定的对象T。这个Object对象主要的转 换,在其内部是直接调用了ObjectConverter.ConvertObjectToType(Object o, Type type, JavaScriptSerializer serializer)方法实现。ObjectConverter.ConvertObjectToType方法主要逻辑依次如下:
在最后一步的“复杂”逻辑中,似乎能够使用提供TypeConverter来转换对象,以此自定义序列化与反序列化能力(事实上,如果单独使用这个方法 时您的确可以这么做),但是事实上在实际使用中作用并不大。因为序列化与反序列化能力主要是应用在Web Service方法访问上的,而在这里的反序列化过程中很难使这段逻辑“遭遇”特殊的对象(虽然我们能够通过自定义JavaScriptConvetor 来“遭遇”这种情况)。在这里,使用TypeConverter是为了转换一些“基础对象”,例如Int32,Double等。另外需要注意的是,我们不 能使用ConvertToType方法直接转换客户端序列化的日期对象,因为日期在客户端会被序列化成“"@23552233@"”传递过来,在反序列化时需要做特殊处理。 将IDictionary<string, object>和IList转化成特定对象的逻辑比较重要,尤其是前者。我们先来看一下它的主要逻辑吧:
相对来说,IList到Object的转换就比较简单了,它能够支持的对象类型有Array,ArrayList,List,List< T>和其余实现IList的类型。注意能够在服务器端反序列化的类型都必须有无参数的构造函数,在转换时依旧会递归调用 ObjectConverter.ConvertObjectToType方法。 2、Deserialize<T>(String) 该方法的作用是将一个JSON字符串转化为类型T。 该方法的第一步,是首先将该字符串转化成为一个中间类型。这个类型可能是个基础类型(Int32,Double,DateTime等),或者 IDictionary<string, object>与IList的互相嵌套(这就是JSON字符串的表示形式,一般来说,最终目标也是基础类型)。但是需要注意是,在将一个“{...}” 形式的字符串片断转换为IDictionary<string, object>之后,如果发现该字典中有关于“__type”的定义,就会调用 ObjectConverter.ConvertObjectToType方法立即将其转换为__type表示的类型,在这个过程中会将调用 Deserialize<T>(String)方法的JavaScriptSerializer对象在各个操作中进行传递,因此起初在那个 JavaScriptSerializer对象中定义的JavaScriptTypeResolver和JavaScriptConverter都会产生 效果。 该方法的第二步,就是将第一步所得到的结果,使用ObjectConverter.ConvertObjectToType方 法将其转换为目标T了。可以发现,由于JSON字符串中“__type”的作用,还是能够在之前描述过的 ObjectConverter.ConvertObjectToType逻辑的第5步中,使TypeConverter起到所需的效果的。如果合理使 用,就能够很方便的进行开发。 3、DeserializeObject(String) 该方法可以说是Deserialize<T>(String)方法的一小部分,它也分作两步进行。其中第一步和 Deserialize<T>(String)方法第一步作用完全一样,而第二步也是使用了 ObjectConverter.ConvertObjectToType方法进行转换。由于和那个方法相比没有指定目标对象T,因此传递给 ObjectConverter.ConvertObjectToType方法的第二个参数则为null,也就是说,如果进行到 IDictionary<string, object>到Object的转换,如果没有指定“__type”,它将保持不变。至于“[...]”类型的JSON字符串,如果没有指定 type,则会默认转换为一个Object数组。 4、Serialize的两个重载方法 这两个方法的作用是使用Object转换为JSON字符串。Serialize(Object)方法会构造一个StringBuilder,再调用Serialize(Object, StringBuilder)方法得到结果,因此我们将目光对准后者。 其实Serialize方法的逻辑相对于Deserialize方法来说简单了不少,毕竟拼接字符串的工作一般总是比解析字符串的工作要容易。 Serialize方法本身也是个递归方法,会递归地序列化一个对象的public属性和变量,因此在序列化一个复杂对象时往往会出现“循环引用” 的状况,这时候就就会抛出异常。这时候JavaScriptConverter就起到其作用了,在序列化某个类型时,会查找serializer中是否有 其对应的JavaScriptConveter,如果有的话,则会通过这个JavaScriptConverter得到一个 IDictionary<string, object>,然后再为这个字典添加“__type”的值,最后再将这个字典对象序列化输出。需要注意的是,得到“__type”值的方式是通过 JavaScriptConverter中的JavaScriptTypeResolver来得到类型的标识字符串。这个逻辑和反序列化操作正好相反。 这些就是ASP.NET AJAX服务器端提供的序列化与反序列化的能力。而且事实上它提供的扩展能力往往也已经足够了,这点着实为我们省去了许许多多的麻烦。 本文出自 “赵劼” 博客,转载请与作者联系! 本文出自 51CTO.COM技术博客 |



jeffz
博客统计信息
热门文章
最新评论
友情链接
