JSON格式在描寫1個(gè)JavaScript對(duì)象1般都能勝任的。包括字符串、數(shù)字、Bool、數(shù)組都能在格式中分辨清楚。
唯1的例外是日期類型,本身無標(biāo)準(zhǔn)可循,很難辨別出日期和字符串。因此各種序列化器都定制了自己的標(biāo)準(zhǔn),例如微軟的Asp.net AJAX的日期格式是:
“/Date(628318530718)/”中間的數(shù)字是ticks。
這個(gè)標(biāo)準(zhǔn)需要序列化和反序列化的雙方都到遵照,例如使用Asp.net AJAX extension序列化生成的字符串中如果含有日期類型,使用JQuery的反序列化就不能正確地還原數(shù)據(jù)。
例如有些使用AJAX異步調(diào)用的場景,如果1個(gè)服務(wù)器真?zhèn)€方法返回1個(gè)對(duì)象,就有可能出現(xiàn)格式不兼容的現(xiàn)象。
微軟本身就有不只1種JSON的序列化機(jī)制,例如WCF下的JSON序列化。還有諸如Json.net之類的第3方工具。
另外,JSON序列化還要關(guān)心其可擴(kuò)大性。畢竟復(fù)雜對(duì)象的序列化,特別是帶有相互援用關(guān)系的對(duì)象,很容易產(chǎn)生無窮遞歸,致使堆棧溢出。
微軟的Asp.net AJAX就提供了1種定制序列化的手段,編寫1個(gè)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);
//解決對(duì)象之間循環(huán)援用的問題
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,定制了1個(gè)JSON序列化器。固然在使用之前,需要先為類型DemoEntity,注冊(cè)此序列化器。
JSONSerializerExecute.RegisterConverter(typeof(DemoEntityConverter));
在1個(gè)AppDomain中,僅僅注冊(cè)1次就行。重復(fù)注冊(cè)也沒有關(guān)系。
上面的例子代碼,可以參照/MCSWebApp/StepByStep/JavascriptConverterDemos/CustomiseJsConverter.aspx
我們系統(tǒng)中的經(jīng)常使用類型,都有對(duì)應(yīng)的序列化器來支持。
至于客戶端和服務(wù)器真?zhèn)€遠(yuǎn)程調(diào)用,我們通過Asp.net AJAX擴(kuò)大的web service來實(shí)現(xiàn),先看看服務(wù)器真?zhèn)€代碼:
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;
}
//如果想在序列化時(shí)疏忽此屬性,請(qǐng)打開下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();
}
}
}
再看看客戶真?zhèn)€代碼:
<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);
//這個(gè)名字空間需要和服務(wù)器端對(duì)應(yīng)
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>
在這個(gè)進(jìn)程中,觸及到的對(duì)象序列化,都會(huì)遵守Asp.net AJAX的JSON序列化機(jī)制。
上面的例子,請(qǐng)參照:
/MCSWebApp/StepByStep/Forms/AJAXClient.aspx