共计 4777 个字符,预计需要花费 12 分钟才能阅读完成。
从 XML 到 JSON
当下利用开发常见的 B / S 架构之下,咱们会遇到很多须要进行前后端数据传输的场景。而在这个传输的过程中,数据通过何种格局传输、形式是否迅速便捷、书写形式是否简略易学,都成为了程序员在开发时要考量的问题。
在 1996 年,W3C(World Wide Web Consortium,万维网联盟)正式颁布了 XML1.0 规范,
XML 采纳规范格局为基于 Web 的利用提供了一个对立进行数据形容和数据交换的规范,不同于 HTML 侧重于解决 ”:如何将文件显示在浏览器中 ”,XML 更加侧重于解决:” 如何将数据以结构化形式形容 ”。
(须要留神的是,XML 并不是一种编程语言,而是一种跨语言的数据格式。)
XML 自身并不简单,然而加上 W3C 制订的 DTD、XSD、XPath、XSLT 等二十多个规范之后,这个简略的数据交换格局平白变得复杂了起来。程序员凡是遇到,只能头大。苦心孤诣钻研大半个月,也不好轻言本人全副分明了。
而此时,推动着技术后退的另一台蒸汽机也被点燃——Ajax 技术开始风行,映衬出 XML 越来越不容忽视的毛病。XML 得以实现是基于 DOM 树,而 DOM 在各种浏览器中的实现细节不尽相同,所以 XML 的跨浏览器兼容性并不好,这时须要一种新的数据负载格局集成到 HTML 页面中,以满足 Ajax 的要求。
终于,在 XML 诞生后的第八年——2002 年,由 Douglas Crockford 开始应用 JSON 这种轻量级数据交换格局。
首条 JSON 信息收回后,最让人们诧异的是,这并不是一个全新的数据格式,它就是 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 类为例,
// 创立用户列表
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 = "王五"});
// 创立一个 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 字段设置残缺的类型名字符串 (如果有命名空间也应蕴含命名空间)。
- 如果自定义类型有循环依赖或是你心愿减小 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 进行序列化和反序列化的工作原理,同时带大家理解了在前端电子表格中要想齐全实现整个内容的数据序列化和反序列化应该如何做。
后续也会为大家带来更多乏味或者庄重的内容~
感觉不错,点个赞再走吧。
扩大浏览
- SpreadJS 产品官网
- Spread JSON 导入 / 导出