JSON序列化


JSON格式在描述一个JavaScript对象一般都能胜任的。包括字符串、数字、Bool、数组都能在格式中分辨清楚。


         唯一的例外是日期类型,本身无标准可循,很难区分出日期和字符串。因此各种序列化器都定制了自己的标准,例如微软的Asp.net AJAX的日期格式是:

         “\/Date(628318530718)\/”中间的数字是ticks。

        

         这个标准需要序列化和反序列化的双方都到遵守,例如使用Asp.net AJAX extension序列化生成的字符串中如果含有日期类型,使用JQuery的反序列化就不能正确地还原数据。

         例如有些使用AJAX异步调用的场景,如果一个服务器端的方法返回一个对象,就有可能出现格式不兼容的现象。

         微软自身就有不只一种JSON的序列化机制,例如WCF下的JSON序列化。还有诸如Json.net之类的第三方工具。

 

         另外,JSON序列化还要关心其可扩展性。毕竟复杂对象的序列化,尤其是带有相互引用关系的对象,很容易产生无限递归,导致堆栈溢出。

         微软的Asp.net AJAX就提供了一种定制序列化的手段,编写一个Converter:

      

   public classDemoEntityConverter : JavaScriptConverter
   {
       public overrideobject Deserialize(IDictionary<string,object>dictionary, Type type,JavaScriptSerializer serializer)
       {
           DemoEntity entity = newDemoEntity();
           entity.P1 = DictionaryHelper.GetValue(dictionary,"P1",string.Empty);
           entity.P2 = DictionaryHelper.GetValue(dictionary,"P2",string.Empty);
           entity.P3 = DictionaryHelper.GetValue(dictionary,"P3",string.Empty);
 
           //解决对象之间循环引用的问题
           if (dictionary.ContainsKey("Entity2"))
           {
               entity.Entity2 = JSONSerializerExecute.Deserialize<DemoEntity2>(dictionary["Entity2"]);
               entity.Entity2.Entity = entity;
           }
 
           return entity;
       }
 
       public overrideIDictionary<string,object> Serialize(objectobj,JavaScriptSerializer serializer)
       {
           IDictionary<string,object> dictionary =new Dictionary<string,object>();
 
           DemoEntity entity = (DemoEntity)obj;
 
           //仅序列化需要的属性,减少json串大小
           DictionaryHelper.AddNonDefaultValue<string,object>(dictionary,"P1", entity.P1);
           DictionaryHelper.AddNonDefaultValue<string,object>(dictionary,"P2", entity.P2);
           DictionaryHelper.AddNonDefaultValue<string,object>(dictionary,"P3", entity.P3);
           dictionary.Add("Entity2",entity.Entity2);
 
           return dictionary;
       }
 
       public overrideIEnumerable<Type>SupportedTypes
       {
           get
           {
               return new Type[] { typeof(DemoEntity) };
           }
       }
   }

         上面的代码中,就为类型DemoEntity,定制了一个JSON序列化器。当然在使用之前,需要先为类型DemoEntity,注册此序列化器。

JSONSerializerExecute.RegisterConverter(typeof(DemoEntityConverter));

         在一个AppDomain中,仅仅注册一次就行。重复注册也没有关系。

         我们系统中的常用类型,都有对应的序列化器来支持。

 至于客户端和服务器端的远程调用,我们通过Asp.net AJAX扩展的web service来实现,先看看服务器端的代码:

namespace StepByStep.Forms
        {
[WebService(Namespace = "http://tempuri.org/")]
   [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
   [System.ComponentModel.ToolboxItem(false)]
   [System.Web.Script.Services.ScriptService]
   public classAJAXService : System.Web.Services.WebService
   {
       public classWebServerInfo
       {
           public DateTimeServerTime
           {
               get;
               set;
           }
 
           //如果想在序列化时忽略此属性,请打开下一行的注释
           //[ScriptIgnore]
           public stringServerInformation
           {
               get;
               set;
           }
       }
 
       [WebMethod]
       public WebServerInfoGetServerInfo()
       {
           WebServerInfo result = new WebServerInfo();
 
           result.ServerTime = DateTime.Now;
           result.ServerInformation = GetServerInformation();
 
           return result;
       }
 
       private staticstring GetServerInformation()
       {
           StringBuilder strB = new StringBuilder();
 
           using (TextWriterwriter =new StringWriter(strB))
           {
               writer.WriteLine("MachineName: {0}",Environment.MachineName);
               writer.WriteLine("OS Version: {0}",Environment.OSVersion.VersionString);
               writer.WriteLine("Is 64 bits: {0}",Environment.Is64BitOperatingSystem.ToString());
               writer.WriteLine("Processor Count: {0}",Environment.ProcessorCount);
           }
 
           return strB.ToString();
       }
   }
   }

 再看看客户端的代码:

         <asp:ScriptManagerrunat="server" ID="scriptManager" EnableScriptGlobalization="true">

       <Services>
           <asp:ServiceReferencePath="~/Forms/AJAXService.asmx"/>
       </Services>
   </asp:ScriptManager>
         <SOA:SubmitButtonrunat="server" Text="GetServer Info" AsyncInvoke="onGetServerInfo" />
         <scripttype="text/javascript">

       function onGetServerInfo() {

           StepByStep.Forms.AJAXService.GetServerInfo(onGetServerInfoSuccess,onFailed);

           //这个名字空间需要和服务器端对应

           return false;

       }     

function onGetServerInfoSuccess(serverInfo) {
           $get("serverInfoText").innerText =serverInfo.ServerTime;
           $get("serverInfoText").innerText +="\n" +serverInfo.ServerInformation;
 
           SubmitButton.resetAllStates();
       }
 
       function onFailed(e) {
           SubmitButton.resetAllStates();
           $showError(e);
       }
 
         </script>


       在这个过程中,涉及到的对象序列化,都会遵循Asp.net AJAX的JSON序列化机制。

       上面的例子,请参照:

      /MCSWebApp/StepByStep/Forms/AJAXClient.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值