從XML到JSON
當下應用開發(fā)常見的B/S架構之下,我們會遇到很多需要進行前后端數據傳輸的場景。而在這個傳輸的過程中,數據通過何種格式傳輸、方式是否迅速便捷、書寫方式是否簡單易學,都成為了程序員在開發(fā)時要考量的問題。
在1996年,W3C(World Wide Web Consortium,萬維網聯盟)正式公布了XML1.0標準,
XML采用標準格式為基于Web的應用提供了一個統(tǒng)一進行數據描述和數據交換的標準,不同于HTML側重于解決:如何將文件顯示在瀏覽器中,XML更加側重于解決:如何將數據以結構化方式描述。
(需要注意的是,XML并不是一種編程語言,而是一種跨語言的數據格式。)
XML本身并不復雜,但是加上W3C制定的DTD、XSD、XPath、XSLT等二十多個標準之后,這個簡單的數據交換格式平白變得復雜了起來。程序員但凡遇到,只能頭大??嘈墓略勓芯看蟀雮€月,也不好輕言自己全部清楚了。
而此時,推動著技術前進的另一臺蒸汽機也被點燃——Ajax技術開始流行,映襯出XML越來越不容忽視的缺點。XML得以實現是基于DOM樹,而DOM在各種瀏覽器中的實現細節(jié)不盡相同,所以XML的跨瀏覽器兼容性并不好,這時需要一種新的數據負載格式集成到HTML頁面中,以滿足Ajax的要求。
終于,在XML誕生后的第八年——2002年,由Douglas Crockford開始使用JSON這種輕量級數據交換格式。
首條JSON信息發(fā)出后,最讓人們驚訝的是,這并不是一個全新的數據格式,它就是JavaScript。
document.domain = 'fudco';parent.session.receive( { to: "session", do: "test", text: "Hello world" } )
而由于這條數據內容本身就是JavaScript,因此不再需要做任何額外解析,使用JS編譯器就可以解決一切。
由于JSON非常簡單,很快就風靡Web世界,并且成為ECMA標準。幾乎所有編程語言都有解析JSON的庫,而在JavaScript中,我們可以直接使用JSON,因為JavaScript內置了JSON的解析。把JavaScript對象變成JSON,就是把這個對象序列化成一個JSON格式的字符串,這樣才能夠通過網絡傳遞給其他計算機。如果我們收到一個JSON格式的字符串,只需要把它反序列化成一個JavaScript對象,就可以在JavaScript中直接使用這個對象了。
Json的序列化和反序列化
正如一道菜做好后,需要裝在盤子里端給顧客,前后端的數據傳輸也是如此。數據通過指定格式,將傳輸的對象序列化為二進制數據流,然后再通過反序列化將數據流內容轉化成為對應的數據對象。
JSON中的數據形式與轉化方式
在JSON中,數據有以下幾種形式:
- 對象:一個沒有順序的"鍵/值",格式如
- 數組:用以設置數值順序,格式如
- 字符串:任意數量的Unicode字符,格式如
進行數據序列化和反序列化的方式有以下三種:
- 使用JavaScriptSerializer類
- 使用DataContractJsonSerializer類
- 使用JSON.NET類庫
以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)建一個JavaScriptSerializer對象
JavaScriptSerializer serializer = new JavaScriptSerializer();
//將用戶列表序列化成JSON
string serializedResult = serializer.Serialize(userList);
//將JOSN反序列化成用戶列表
List<UserInfo> deserializeResult = serializer.Deserialize<List<UserInfo>>(serializedResult);
只需要調用對應方法,就可以直接實現對數據內容的序列化。
你以為到這里就結束了嗎,當然沒有。在實際應用中,數據本身的處理并沒有什么難度,真正需要考慮解決的問題是,數據本身附加的屬性、設置。就以我們自身為例,客戶在純前端電子表格中對JSON數據傳輸的真實需求是,這段數據需要保證所有可視化內容的完整傳輸。
純前端表格中的JSON數據處理
在實際處理用戶需求時,用戶在設置好如下圖單元格后,不僅僅是單元格內存在數字,還會遇到單元格本身的樣式、自定義函數、 自定義格式、自定義函數迷你圖、自定義標簽,以及自定義行篩選。
我們打開相關的代碼,可以清楚地看到在格式中這些對單元格的設置,都被保存了下來。
在這個圖中,我們可以看到不同類型的數據內容都可以完成序列化和反序列化的過程。在使用自定義序列化的過程中,查看相關代碼,處理序列化的核心是typeName 字段在調用toJSON函數的過程,比如,可以將此類姓名和window對象聯系。而反序列化時,調用 getTypeFromString 函數來獲取類型名并且構造類型實例對象,然后調用類型實例上的 fromJSON方法。
此外還有許多其他的屬性內容,下面列舉其他樣式設置的例子:
背景圖片:
//這個例子設置了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);
水印設置:
//此示例設置水印的單元格填充。
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);
主題字體:
//這個例子使用了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");
還有許多對于單元格的設置,這些樣式內容都可以被完整保存下來,作為json數據進行傳輸,帶來真正的表格json數據傳輸的便利。
使用過程中需要注意以下問題:
- 給 typeName 字段設置完整的類型名字符串(如果有命名空間也應包含命名空間)。
- 如果自定義類型有循環(huán)依賴或是你希望減小JSON 數據的大小,亦或是你有其他更高級的需求,那么你的自定義類型需要重寫toJSON和fromJSON方法。
- 如果自定義類型定義在一個閉包中,換句話說,你不希望將自定義類型定義在 window 對象上,你需要重寫 getTypeFromString 函數來手動解析類型的字符串。
代碼示例:
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;
}
};
總結
本文詳細為大家介紹了數據傳輸從XML到JSON的故事,以及json進行序列化和反序列化的工作原理,同時帶大家了解了在前端電子表格中要想完全實現整個內容的數據序列化和反序列化應該如何做。
后續(xù)也會為大家?guī)砀嘤腥せ蛘邍烂C的內容~
覺得不錯,點個贊再走吧。
本文摘自 :https://www.cnblogs.com/