DataContractJsonSerializer和JavaScriptSerializer内部实现差异

定义一个下面这样的类,此类有Serializable属性,并且有一个属性的定义没有使用自动属性来实现。

[Serializable]
 public class Users
 {
     public int UserID { get; set; }
     public string UserName { get; set; }
     public string UserEmail { get; set; }
     private string _testProperty;
     public string TestProperty
     {
         get { return _testProperty; }

         set { _testProperty = value; }
     }
 }

然后分别使用DataContractJsonSerializer和JavaScriptSerializer对此对象的示例进行序列化。
使用DataContractJsonSerializer序列化后的结果。

{"_testProperty":"TestPropertyValue","<UserEmail>k__BackingField":"[email protected]",
"<UserID>k__BackingField":1,"<UserName>k__BackingField":"Parry"}

使用JavaScriptSerializer序列化后的结果。

{

"UserID":1,

"UserName":"Parry",

"UserEmail":"[email protected]",

"TestProperty":"TestPropertyValue"

}

DataContractJsonSerializer和JavaScriptSerializer的实现差异
DataContractJsonSerializer在.NET Framework 3.5中引入,主要因为WCF的引入而添加了这个对象序列化的基本方法,并且微软同时将JavaScriptSerializer打上了过时(obsolete)的标签,编译时就会有警告出现。
而在.NET Framework 3.5 SP1中,又将JavaScriptSerializer的“过时”标签给去掉了。
使用Reflector去比较这两个类的内部实现发现,DataContractJsonSerializer在对象序列化时进行了更为严格的检查,感兴趣的可以去System.Runtime.Serialization.Json下面的核心方法InternalWriteObjectContent去看其实现。
而在.NET Framework 3.5引入的自动属性,实际上就是个语法糖,编译器还是会生成一个int类型的<Name>k_BackingField的私有字段作为这个属性的后端字段,内部还是和以前的get/set方法一样。
所以直接使用DataContractJsonSerializer进行序列化时,有将编译器生成的k_BackingField带了出来。
而JavaScriptSerializer的实现则非常的简单,将属性名和属性值分别存储在Dictionary里,然后进行字符串拼接返回而已,所以对类几乎没有检查并且对复杂类的支持不太好。
下面是JavaScriptSerializer里面的核心方法SerializeValue的实现。

private void SerializeValue(object o, StringBuilder sb, int depth, Hashtable objectsInUse,
 SerializationFormat serializationFormat, MemberInfo currentMember = null) {
     if (++depth > _recursionLimit) {
         throw new ArgumentException(AtlasWeb.JSON_DepthLimitExceeded);
     }
     // Check whether a custom converter is available for this type.
     JavaScriptConverter converter = null;
     if (o != null && ConverterExistsForType(o.GetType(), out converter)) {
         IDictionary<string, object> dict = converter.Serialize(o, this);
         if (TypeResolver != null) {
             string typeString = TypeResolver.ResolveTypeId(o.GetType());
             if (typeString != null) {
                 dict[ServerTypeFieldName] = typeString;
             }
         }
         sb.Append(Serialize(dict, serializationFormat));
         return;
     }
     SerializeValueInternal(o, sb, depth, objectsInUse, serializationFormat, currentMember);
 }

解决方法:

如果一定要使用DataContractJsonSerializer,只有当为类加上[DataContract]属性,并且为需要序列化的属性加上[DataMember]后,使用DataContractJsonSerializer才可以生成干净、整洁的JSON数据。
而当我们使用一些不能修改的类定义,如上面的Users类定义,我们没有权限去修改其定义,那么就可以使用JavaScriptSerializer去进行JSON序列化。
当然第三方的Json.NET(Newtonsoft.Json)也是可以实现了,并且在支持的功能和效率方面往往是一个更好的选择,在这里看它和DataContractJsonSerializer以及JavaScriptSerializer的对比。
所以在使用时需要稍微注意下这三个JSON序列化方法的差异,根据自己的需求灵活选择合适的组件。

时间: 2024-10-07 09:24:13

DataContractJsonSerializer和JavaScriptSerializer内部实现差异的相关文章

Silverlight和WPF中DataContractJsonSerializer对时间的处理差异

原创文章转载请注明出处:@协思, http://zeeman.cnblogs.com Silverlight脱胎于WPF,他们的行为不完全并不完全相同,DataContractJsonSerializer对时间处理有一个坑. 我们知道.NET在序列化实体为JSON的时候,会将DateTime处理为[/Date(xxxxx)]的字符串.如果Client端将这个属性不定义为DateTime,而定义为String会发生什么呢? 常规思维下我们都会认为String Value就是[/Date(xxxxx

Asp.Net JSON序列号与反序列化

问题的引子 先来看问题的引子. 定义一个下面这样的类,此类有Serializable属性,并且有一个属性的定义没有使用自动属性来实现. [Serializable] public class Users { public int UserID { get; set; } public string UserName { get; set; } public string UserEmail { get; set; } private string _testProperty; public st

什么是POSP?系统逻辑是什么?pos收单必读

POSProxy,POS前置系统.主要用于管理前端的POS机具和交易的转发,具体功能有: 1. POS机具的密钥及下载管理: 2. 交易的合法检测和过滤: 3. 交易监控和分流: 4. 对账务后台系统起着安全保护和防火墙的作用: 5. 交易的并发控制和交易排队: 6. POS交易的接入和交易报文的转换: 7. 管理各个接入方向的启用和关闭. 有了POSP后,可以扩展更多业务,进行更多的业务分发和渠道接入,如代缴费.网上支付.第三方的业务等,可以进行平台的运营业务 从逻辑架构上,整个应用分为渠道层

《人类简史》笔记

ausust 2013-09-12 21:13 第一周:什么是历史?把自130亿年前的宇宙大爆炸开始的物质.能量.时间.空间的产生和相互作用称作“物理”阶段:大爆炸30万年之后,物质相互作用形成原子分子等复杂结构,此为“化学”阶段:40亿年前,地球上的粒子结合成更加复杂的结构,形成有机体/生命体,是“生物”阶段:7万年前,复杂有机体进化出智人种族,智人群体逐渐壮大演化出复杂的社会.文化结构,是“历史”阶段.历史是宇宙复杂演化中的一环,与前几者无明显界限.历史的几大分期:7万年前开始的认知革命,1

数据挖掘十大算法之决策树详解(1)

在2006年12月召开的 IEEE 数据挖掘国际会议上(ICDM, International Conference on Data Mining),与会的各位专家选出了当时的十大数据挖掘算法( top 10 data mining algorithms ),可以参见文献[1].本博客已经介绍过的位列十大算法之中的算法包括: [1] k-means算法(http://blog.csdn.net/baimafujinji/article/details/50570824) [2] 支持向量机SVM

【遇见大咖】测试界:你的年终奖有多少?

掐指一算,还有两周就过年了! 别人家的年会也开始在朋友圈陆续上演 这个时候比较牵动人心的 除了年会上那点小礼品 还有更多的是年终奖吧! 其实年会和年终奖一样 一方面对部分员工充满了激励 另一方面也像达摩克利斯之剑高悬心间 同一桌的伙伴亲密无间一年 这一顿吃完也可能就意味着散伙呀! 多少熟悉的朋友 第二年不会出现在次年的年会饭桌上? 淘汰或被淘汰 企业的KPI考核每年总会有些限量的名额留给少数一年来都给大家拖后腿的同志,对老板和同事们来说,年终来临的时候终于意味着报仇的时间到了,虽然不至于一封冷冰

人类简史课整理

<人类简史>笔记: 第一周: 什么是历史? 历史的几大分期: 7万年前开始的认知革命,12000年前开始的农业革命,500年前开始的科学革命. 划分物种的重要依据及命名: 两个个体间能否通过交配诞下有繁殖能力的后代.为什么只有人类的大脑不断扩大仍旧是个迷题. 为什么要直立行走? 提供更宽阔的视野,空出双手做其他用途.缺点:脊椎和腿部肌肉承受巨大重量.. .. .. 第二周: 7万年前智人进步: 逐渐遍布亚非欧大陆,4.5-5万年前抵达澳大利亚,1.5万年前左右抵达美洲:(Gossip)的重要性

C# 对象与JSON字符串互相转换的几种方式

出自:http://blog.csdn.net/testcs_dn/article/details/78150046?locationNum=6&fps=1 目录(?)[-] 方法一DoNet20 需要借助于NewtonsoftJsondll 方法二DataContractJsonSerializer 方法三JavaScriptSerializer 功能对比 性能对比 JSON转C实体类 相关参考 c json数据解析将字符串json格式数据转换成对象 Jsonnet实现方便的Json转Cdyn

MS SQL Server数据库两个库之间相同数据表名内容批量对比方法

上一篇"导出记录数量对比-软件测试方法(一)",主要介绍数据导出结果记录数量和原始正常好库的记录数量精确对比,测试软件导出少数据的相关bug.本文测试方法旨在更精确比对表记录内部数据差异,记录数量的对比只是恢复准确率的必要条件,而记录内部的字段数据内容是否一致,才是比较的终极目标. 一. 测试目的:在很多情况下,数据导出是以记录数量来衡量是否齐全.在某些情况下,数据记录数量导出是一致的,但,记录内部数据却出现差异,比如某些数字字段,一旦出现差异,其结果将带来不准确.本测试大纲目的是比对