JSON序列化
JSON格式在描写1个JavaScript对象1般都能胜任的。包括字符串、数字、Bool、数组都能在格式中分辨清楚。
唯1的例外是日期类型,本身无标准可循,很难辨别出日期和字符串。因此各种序列化器都定制了自己的标准,例如微软的Asp.net AJAX的日期格式是: “/Date(628318530718)/”中间的数字是ticks。
这个标准需要序列化和反序列化的双方都到遵照,例如使用Asp.net AJAX extension序列化生成的字符串中如果含有日期类型,使用JQuery的反序列化就不能正确地还原数据。 例如有些使用AJAX异步调用的场景,如果1个服务器真个方法返回1个对象,就有可能出现格式不兼容的现象。 微软本身就有不只1种JSON的序列化机制,例如WCF下的JSON序列化。还有诸如Json.net之类的第3方工具。
另外,JSON序列化还要关心其可扩大性。毕竟复杂对象的序列化,特别是带有相互援用关系的对象,很容易产生无穷递归,致使堆栈溢出。 微软的Asp.net AJAX就提供了1种定制序列化的手段,编写1个Converter: public class DemoEntityConverter : 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,entity.P1); DictionaryHelper.AddNonDefaultValue<string,entity.P2); DictionaryHelper.AddNonDefaultValue<string,entity.P3); dictionary.Add("Entity2",entity.Entity2);
return dictionary; }
public overrideIEnumerable<Type>SupportedTypes { get { return new Type[] { typeof(DemoEntity) }; } } } 上面的代码中,就为类型DemoEntity,定制了1个JSON序列化器。固然在使用之前,需要先为类型DemoEntity,注册此序列化器。 JSONSerializerExecute.RegisterConverter(typeof(DemoEntityConverter)); 在1个AppDomain中,仅仅注册1次就行。重复注册也没有关系。 上面的例子代码,可以参照/MCSWebApp/StepByStep/JavascriptConverterDemos/CustomiseJsConverter.aspx 我们系统中的经常使用类型,都有对应的序列化器来支持。
至于客户端和服务器真个远程调用,我们通过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 class AJAXService : System.Web.Services.WebService { public class WebServerInfo { public DateTimeServerTime { get; set; }
//如果想在序列化时疏忽此属性,请打开下1行的注释 //[ScriptIgnore] public stringServerInformation { get; set; } }
[WebMethod] public WebServerInfoGetServerInfo() { WebServerInfo result = new WebServerInfo();
result.ServerTime = DateTime.Now; result.ServerInformation = GetServerInformation();
return result; }
private static string 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:ScriptManager runat="server" ID="scriptManager" EnableScriptGlobalization="true"> <Services> <asp:ServiceReference Path="~/Forms/AJAXService.asmx"/> </Services> </asp:ScriptManager> <SOA:SubmitButton runat="server" Text="GetServer Info" AsyncInvoke="onGetServerInfo" /> <script type="text/javascript"> function onGetServerInfo() { StepByStep.Forms.AJAXService.GetServerInfo(onGetServerInfoSuccess,onFailed); //这个名字空间需要和服务器端对应 return false; }
function onGetServerInfoSuccess(serverInfo) { $get("serverInfoText").innerText =serverInfo.ServerTime; $get("serverInfoText").innerText +=" " +serverInfo.ServerInformation;
SubmitButton.resetAllStates(); }
function onFailed(e) { SubmitButton.resetAllStates(); $showError(e); }
</script>
在这个进程中,触及到的对象序列化,都会遵守Asp.net AJAX的JSON序列化机制。 上面的例子,请参照: /MCSWebApp/StepByStep/Forms/AJAXClient.aspx (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |