從XML到JSON
當(dāng)下應(yīng)用開(kāi)發(fā)常見(jiàn)的B/S架構(gòu)之下,我們會(huì)遇到很多需要進(jìn)行前后端數(shù)據(jù)傳輸?shù)膱?chǎng)景。而在這個(gè)傳輸?shù)倪^(guò)程中,數(shù)據(jù)通過(guò)何種格式傳輸、方式是否迅速便捷、書寫方式是否簡(jiǎn)單易學(xué),都成為了程序員在開(kāi)發(fā)時(shí)要考量的問(wèn)題。
在1996年,W3C(World Wide Web Consortium,萬(wàn)維網(wǎng)聯(lián)盟)正式公布了XML1.0標(biāo)準(zhǔn),
XML采用標(biāo)準(zhǔn)格式為基于Web的應(yīng)用提供了一個(gè)統(tǒng)一進(jìn)行數(shù)據(jù)描述和數(shù)據(jù)交換的標(biāo)準(zhǔn),不同于HTML側(cè)重于解決:如何將文件顯示在瀏覽器中,XML更加側(cè)重于解決:如何將數(shù)據(jù)以結(jié)構(gòu)化方式描述。
(需要注意的是,XML并不是一種編程語(yǔ)言,而是一種跨語(yǔ)言的數(shù)據(jù)格式。)
XML本身并不復(fù)雜,但是加上W3C制定的DTD、XSD、XPath、XSLT等二十多個(gè)標(biāo)準(zhǔn)之后,這個(gè)簡(jiǎn)單的數(shù)據(jù)交換格式平白變得復(fù)雜了起來(lái)。程序員但凡遇到,只能頭大。苦心孤詣研究大半個(gè)月,也不好輕言自己全部清楚了。
而此時(shí),推動(dòng)著技術(shù)前進(jìn)的另一臺(tái)蒸汽機(jī)也被點(diǎn)燃——Ajax技術(shù)開(kāi)始流行,映襯出XML越來(lái)越不容忽視的缺點(diǎn)。XML得以實(shí)現(xiàn)是基于DOM樹(shù),而DOM在各種瀏覽器中的實(shí)現(xiàn)細(xì)節(jié)不盡相同,所以XML的跨瀏覽器兼容性并不好,這時(shí)需要一種新的數(shù)據(jù)負(fù)載格式集成到HTML頁(yè)面中,以滿足Ajax的要求。
終于,在XML誕生后的第八年——2002年,由Douglas Crockford開(kāi)始使用JSON這種輕量級(jí)數(shù)據(jù)交換格式。
首條JSON信息發(fā)出后,最讓人們驚訝的是,這并不是一個(gè)全新的數(shù)據(jù)格式,它就是JavaScript。
document.domain = 'fudco';parent.session.receive( { to: "session", do: "test", text: "Hello world" } )
而由于這條數(shù)據(jù)內(nèi)容本身就是JavaScript,因此不再需要做任何額外解析,使用JS編譯器就可以解決一切。
由于JSON非常簡(jiǎn)單,很快就風(fēng)靡Web世界,并且成為ECMA標(biāo)準(zhǔn)。幾乎所有編程語(yǔ)言都有解析JSON的庫(kù),而在JavaScript中,我們可以直接使用JSON,因?yàn)镴avaScript內(nèi)置了JSON的解析。把JavaScript對(duì)象變成JSON,就是把這個(gè)對(duì)象序列化成一個(gè)JSON格式的字符串,這樣才能夠通過(guò)網(wǎng)絡(luò)傳遞給其他計(jì)算機(jī)。如果我們收到一個(gè)JSON格式的字符串,只需要把它反序列化成一個(gè)JavaScript對(duì)象,就可以在JavaScript中直接使用這個(gè)對(duì)象了。
Json的序列化和反序列化
正如一道菜做好后,需要裝在盤子里端給顧客,前后端的數(shù)據(jù)傳輸也是如此。數(shù)據(jù)通過(guò)指定格式,將傳輸?shù)膶?duì)象序列化為二進(jìn)制數(shù)據(jù)流,然后再通過(guò)反序列化將數(shù)據(jù)流內(nèi)容轉(zhuǎn)化成為對(duì)應(yīng)的數(shù)據(jù)對(duì)象。
JSON中的數(shù)據(jù)形式與轉(zhuǎn)化方式
在JSON中,數(shù)據(jù)有以下幾種形式:
- 對(duì)象:一個(gè)沒(méi)有順序的"鍵/值",格式如
- 數(shù)組:用以設(shè)置數(shù)值順序,格式如
- 字符串:任意數(shù)量的Unicode字符,格式如
進(jìn)行數(shù)據(jù)序列化和反序列化的方式有以下三種:
- 使用JavaScriptSerializer類
- 使用DataContractJsonSerializer類
- 使用JSON.NET類庫(kù)
以JavaScriptSerializer類為例,
//創(chuàng)建用戶列表
List<UserInfo> userList = new List<UserInfo>();
userList.Add(new UserInfo() { ID = 1, Name = "張三", CreateTime = DateTime.Now });
userList.Add(new UserInfo() { ID = 2, Name = "李四", CreateTime = DateTime.Now });
userList.Add(new UserInfo() { ID = 2, Name = "王五" });
//創(chuàng)建一個(gè)JavaScriptSerializer對(duì)象
JavaScriptSerializer serializer = new JavaScriptSerializer();
//將用戶列表序列化成JSON
string serializedResult = serializer.Serialize(userList);
//將JOSN反序列化成用戶列表
List<UserInfo> deserializeResult = serializer.Deserialize<List<UserInfo>>(serializedResult);
只需要調(diào)用對(duì)應(yīng)方法,就可以直接實(shí)現(xiàn)對(duì)數(shù)據(jù)內(nèi)容的序列化。
你以為到這里就結(jié)束了嗎,當(dāng)然沒(méi)有。在實(shí)際應(yīng)用中,數(shù)據(jù)本身的處理并沒(méi)有什么難度,真正需要考慮解決的問(wèn)題是,數(shù)據(jù)本身附加的屬性、設(shè)置。就以我們自身為例,客戶在純前端電子表格中對(duì)JSON數(shù)據(jù)傳輸?shù)恼鎸?shí)需求是,這段數(shù)據(jù)需要保證所有可視化內(nèi)容的完整傳輸。
純前端表格中的JSON數(shù)據(jù)處理
在實(shí)際處理用戶需求時(shí),用戶在設(shè)置好如下圖單元格后,不僅僅是單元格內(nèi)存在數(shù)字,還會(huì)遇到單元格本身的樣式、自定義函數(shù)、 自定義格式、自定義函數(shù)迷你圖、自定義標(biāo)簽,以及自定義行篩選。
我們打開(kāi)相關(guān)的代碼,可以清楚地看到在格式中這些對(duì)單元格的設(shè)置,都被保存了下來(lái)。
在這個(gè)圖中,我們可以看到不同類型的數(shù)據(jù)內(nèi)容都可以完成序列化和反序列化的過(guò)程。在使用自定義序列化的過(guò)程中,查看相關(guān)代碼,處理序列化的核心是typeName 字段在調(diào)用toJSON函數(shù)的過(guò)程,比如,可以將此類姓名和window對(duì)象聯(lián)系。而反序列化時(shí),調(diào)用 getTypeFromString 函數(shù)來(lái)獲取類型名并且構(gòu)造類型實(shí)例對(duì)象,然后調(diào)用類型實(shí)例上的 fromJSON方法。
此外還有許多其他的屬性內(nèi)容,下面列舉其他樣式設(shè)置的例子:
背景圖片:
//這個(gè)例子設(shè)置了backgroundImageLayout屬性。
var style = new GC.Spread.Sheets.Style();
style.backColor = "lightgreen";
style.backgroundImage = "/css/images/quarter1.png";
style.backgroundImageLayout = GC.Spread.Sheets.ImageLayout.center;
activeSheet.setStyle(1,1,style,GC.Spread.Sheets.SheetArea.viewport);
水印設(shè)置:
//此示例設(shè)置水印的單元格填充。
var type = new GC.Spread.Sheets.Style();
type.watermark = "User name";
type.cellPadding = "20";
type.labelOptions = {alignment:GC.Spread.Sheets.LabelAlignment.topLeft, visibility: GC.Spread.Sheets.LabelVisibility.visible};
activeSheet.setStyle(0, 1, type);
activeSheet.getRange(0, -1, 1, -1, GC.Spread.Sheets.SheetArea.viewport).height(60);
activeSheet.getRange(-1, 1, -1, 1).width(150);
var combo = new GC.Spread.Sheets.CellTypes.ComboBox();
combo.items([{ text: "Oranges", value: "11k" }, { text: "Apples", value: "15k" }, { text: "Grape", value: "100k" }]);
combo.editorValueType(GC.Spread.Sheets.CellTypes.EditorValueType.text);
activeSheet.setCellType(2, 1, combo, GC.Spread.Sheets.SheetArea.viewport);
activeSheet.getCell(2, 1, GC.Spread.Sheets.SheetArea.viewport).watermark("ComboBox Cell Type").cellPadding('10 10 20 10');
activeSheet.getCell(2, 1, GC.Spread.Sheets.SheetArea.viewport).labelOptions({alignment: GC.Spread.Sheets.LabelAlignment.bottomCenter, foreColor: 'yellowgreen', font: 'bold 15px Arial'});
activeSheet.getRange(2, -1, 1, -1, GC.Spread.Sheets.SheetArea.viewport).height(60);
主題字體:
//這個(gè)例子使用了themeFont屬性。
var style = new GC.Spread.Sheets.Style();
style.formatter = "0.000%";
style.themeFont = "Body";
activeSheet.setStyle(1,1,style,GC.Spread.Sheets.SheetArea.viewport);
activeSheet.getCell(1,1).value("11");
還有許多對(duì)于單元格的設(shè)置,這些樣式內(nèi)容都可以被完整保存下來(lái),作為json數(shù)據(jù)進(jìn)行傳輸,帶來(lái)真正的表格json數(shù)據(jù)傳輸?shù)谋憷?/p>
使用過(guò)程中需要注意以下問(wèn)題:
- 給 typeName 字段設(shè)置完整的類型名字符串(如果有命名空間也應(yīng)包含命名空間)。
- 如果自定義類型有循環(huán)依賴或是你希望減小JSON 數(shù)據(jù)的大小,亦或是你有其他更高級(jí)的需求,那么你的自定義類型需要重寫toJSON和fromJSON方法。
- 如果自定義類型定義在一個(gè)閉包中,換句話說(shuō),你不希望將自定義類型定義在 window 對(duì)象上,你需要重寫 getTypeFromString 函數(shù)來(lái)手動(dòng)解析類型的字符串。
代碼示例:
GC.Spread.Sheets.getTypeFromString = function(typeString) {
switch (typeString) {
case "MyFormatter":
return MyFormatter;
case "MyRowFilter":
return MyRowFilter;
default:
return oldFun.apply(this, arguments);
}
};
MyTag.prototype.toJSON = function() {
return {
typeName: this.typeName, //necessary
name: this.name,
age: this.age
};
};
MyTag.prototype.fromJSON = function(settings) {
if (settings.name !== undefined) {
this.name = settings.name;
}
if (settings.age !== undefined) {
this.age = settings.age;
}
};
總結(jié)
本文詳細(xì)為大家介紹了數(shù)據(jù)傳輸從XML到JSON的故事,以及json進(jìn)行序列化和反序列化的工作原理,同時(shí)帶大家了解了在前端電子表格中要想完全實(shí)現(xiàn)整個(gè)內(nèi)容的數(shù)據(jù)序列化和反序列化應(yīng)該如何做。
后續(xù)也會(huì)為大家?guī)?lái)更多有趣或者嚴(yán)肅的內(nèi)容~
覺(jué)得不錯(cuò),點(diǎn)個(gè)贊再走吧。
本文摘自 :https://www.cnblogs.com/