探索dojo/json

难度:中等
Dojo版本:1.7+
原作者:Kris Zyp
译者:Oliver (zhuxw1984@gmail.com)

(年初翻译过Kris Zyp的另一篇介绍dojo/json的文章: Dojo的内建JSON解析模块,本文相比那篇文章更为详细,着重介绍了新老API的对比,对一些API的特殊用法也解释得比较清楚。——译者注)

Dojo长久以来一直通过dojo.fromJson()和dojo.toJson对JSON操作提供良好的支持,但随着ECMAScript 5的JSON对象的出现及其API在浏览器中的普及,现在对JSON的解析和生成操作都有了标准化的API。Dojo1.7新加入的一个模块遵循了这个标准,它使Dojo在浏览器原生JSON对象存在的时候直接交给浏览器来生成或解析JSON。使用这个原生JSON对象的速度更快,同时,dojo/json模块采用了集成到打包系统中的功能检测系统(has() API),因此可以通过打包系统创建出针对某些浏览器的特殊包(例如移动设备包),这些包中的json模块将只有几字节。

使用dojo/json

要引入dojo/json模块,只需将其包含在依赖项列表中即可,就像加载其他模块一样:
define(["dojo/json"], function(JSON){
    //变量JSON可用于JSON数据的解析或串行化
});
要解析一个JSON字符串,我们只需直接调用parse()方法:
define(["dojo/json"], function(JSON){
    var someJsonString = getData();
    // 解析JSON字符串
    var myData = JSON.parse(someJsonString);
});
dojo/json的parse()方法与dojo.fromJson()有一些细微的差别。这两个都能正确解析任何有效的JSON,然而,parse方法最终会委托给原生的JSON解析器,这意味着你必须传给它格式上真正严格有效的JSON字符串才能保证正确的结果,而另一方面,dojo.fromJson()一直使用eval()方法来解析,因此它能接受任意有效的JavaScript表达式。为了保证向后兼容,dojo.fromJson()将仍然接受任意有效的JavaScript表达式,但dojo/json的parse()方法只能接受严格有效的JSON。

保证安全严格的解析

如果原生JSON解析器不可用,dojo/json默认会采用eval()方法来解析JSON。一般而言这个方法还是比较快的,但如果你需要解析来自非可信源的JSON,就应当使用严格模式(strict mode)。可以将parse()方法的第二个参数设置为true来启用严格模式。例如:
var someJsonString = getData();
// 解析JSON字符串
var myData = JSON.parse(someJsonString, true);
当原生JSON解析不可用时,严格模式解析会显得稍慢一些(这是因为需要做额外的检查)。而当原生JSON解析可用时,这第二个参数将被忽略,因为解析永远是严格的(而且一样快)。如下图所示,当原生解析不可用时,严格模式比非严格模式要慢2-3倍。原生解析的速度优势非常明显,因此dojo/json总是会优先考虑使用原生解析,而不管是否设置了严格模式参数。dojo/fromJson()函数从不使用原生解析,因此要比使用了原生解析的dojo/json慢3-4倍。
性能分析图
通常在服务器端采用安全措施要比在客户端更好,因此如果你从你自己的服务器获取数据,最好在服务器端使用一个安全有效的JSON串行化工具,而不是依赖于客户端的安全检查。parse()函数的严格模式应该只被用于来自非可信源的数据。

JSON串行化

dojo/json模块也可以用于串行化JSON。同样,这也是基于原生的JSON API,只要原生的JSON串行化函数可用就会交给它完成。串行化很简单,只需要传递一个JavaScript对象、数组、或者原始值给dojo/json模块的stringify函数:
define(["dojo/json"], function(JSON){
    var object = {foo:"bar"};
    // 串行化为JSON字符串
    var serialized = JSON.stringify(object); // 将返回'{"foo":"bar"}'
});
stringify方法还能接受一个replacer函数,可以用于对自定义数据类型的串行化。例如我们可以通过这个函数把日期数据串行化为UTC毫秒格式。另外,我们也可以用空格使串行化的数据具有易于阅读的缩进。要启用这个易读模式,只需将空格作为第三个参数:
var object = {nested:{props:true}};
// 串行化为JSON字符串
var serialized = JSON.stringify(object, null, "  "); // 返回具有缩进格式的串行化对象
stringify()函数非常类似于以前的dojo.toJson()函数,但还是有一些不同:
  • dojo.fromJson()函数会在它遇到的每个对象中寻找json()或__json__()方法作为自定义的串行化方法,但stringify()则会找toJson()方法。
  • dojo.fromJson()函数不接受replacer函数作为参数,其第二个参数只是一个布尔值,表示是否以美观的形式(缩进)输出结果。如果使用美观形式(传true),就会使用dojo.toJsonIndentStr作为缩进字符串。

在无Base的Dojo中使用dojo/json

Dojo1.7和1.8设计成可以不需要完整的Dojo Base库就能打包应用。当Dojo Base在gzip后的大小小于40KB时,一些应用(尤其是移动设备上的应用)可能希望能做到代码最小化。dojo/json模块是Dojo中不再需要Dojo Base的众多模块之一。这个模块只需要一个模块加载器就能运行,没有任何其他依赖项。这使得超轻量级的应用成为可能。可参考 这篇博客文章进一步了解如何打造你自己的Dojo包。

小结

Dojo1.7和1.8中处理JSON的方法:
  • 解析来自于可信源的JSON —— 使用dojo/json的parse(str)方法
  • 解析来自于非可信源的JSON —— 使用dojo/json的parse(str, true)方法
  • 解析来自可信源的JavaScript表达式(包含JSON)—— 使用dojo.fromJson(str)
  • 将对象或原始值串行化为JSON —— 使用dojo/json的stringify(value)方法。
  • 以美观的缩进形式串行化对象或原始值 —— 使用dojo/json的stringify(value,  "  ")
在比较新的浏览器上(包括所有近期版本的chrome、sarari、firefox、opera以及IE8或更高版本的IE),新的dojo/json模块与dojo.fromJson()/dojo.toJson()相比明显具有更好的性能和更小的代码量。
  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>通过属性查询地图服务中的信息</title> <link rel="stylesheet" href="https://js.arcgis.com/3.39/esri/css/esri.css"> <!-- <link rel="stylesheet" type="text/css" href="./css/esri.css" /> --> <link rel="stylesheet" href="https://js.arcgis.com/3.40/esri/themes/calcite/dijit/calcite.css"> <script src="https://js.arcgis.com/3.41/"></script> <script> require(["esri/map", //加载地图组件 "dojo/dom", "dojo/on", "esri/InfoTemplate", "esri/graphic", "esri/geometry/Point",//加载点对象组件 "esri/symbols/SimpleMarkerSymbol", "esri/geometry/Extent",//加载范围组件 "esri/layers/FeatureLayer", //加载FeatureLayer地图组件 // "esri/dijit/FeatureTable", "esri/layers/WebTiledLayer", //加载切片地图组件 "esri/layers/ArcGISDynamicMapServiceLayer",//加载动态地图组件 "esri/symbols/SimpleFillSymbol", "esri/renderers/UniqueValueRenderer", "esri/tasks/query", "esri/tasks/QueryTask", "esri/Color", "dojo/domReady!" ], function (Map, dom, on, InfoTemplate, Graphic, Point, SimpleMarkerSymbol,Extent, FeatureLayer, WebTiledLayer, ArcGISDynamicMapServiceLayer, SimpleFillSymbol, UniqueValueRenderer, Query, QueryTask, Color, GeoJsonLayer) { //初始化地图容器 // map = new Map("map", { logo: false, slider: false }, {zoom: 8}); map = new Map("map", { center: [109.33789 , 29.57985], basemap: "satellite", zoom: 10, sliderStyle: "small", logo: false }); // 创建底图 var basemap = new esri.layers.ArcGISTiledMapServiceLayer("http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"); map.addLayer(basemap,0); // 创建动态图层 var dynamicLayer = new ArcGISDynamicMapServiceLayer("http://116.62.63.94:6080/arcgis/rest/services/sanhuxiangtest/MapServer"); map.addLayer(dynamicLayer,99); }) </script> </head> <body class="tundra"> <div id="map" style="width:900px; height:580px; border:1px solid #000;"></div> 类别名称:<input class="nm" type="text"> </body> </html>
07-15

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值