`
zjf201172653
  • 浏览: 47550 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

说说JSON和JSONP 也许你会豁然开朗

阅读更多

说说JSON和JSONP 也许你会豁然开朗

转自   http://www.jb51.net/article/31167.htm

 

前言

  由于Sencha Touch 2这种开发模式的特性,基本决定了它原生的数据交互行为几乎只能通过AJAX来实现。

   当然了,通过调用强大的PhoneGap插件然后打包,你可以实现100%的Socket通讯和本地数据库功能,又或者通过HTML5的 WebSocket也可以实现与服务器的通讯和服务端推功能,但这两种方式都有其局限性,前者需要PhoneGap支持,后者要求用户设备必须支持 WebSocket,因此都不能算是ST2的原生解决方案,原生的只有AJAX。

  说到AJAX就会不可避免的面临两个问题,第一个是AJAX以何种格式来交换数据?第二个是跨域的需求如何解决?这两个问题目前都有不同的解决方案,比如数据可以用自定义字符串或者用XML来描述,跨域可以通过服务器端代理来解决。

  但到目前为止最被推崇或者说首选的方案还是用JSON来传数据,靠JSONP来跨域。而这就是本文将要讲述的内容。

   JSON(JavaScript Object Notation)和JSONP(JSON with Padding)虽然只有一个字母的差别,但其实他们根本不是一回事儿:JSON是一种数据交换格式,而JSONP是一种依靠开发人员的聪明才智创造出的 一种非官方跨域数据交互协议。我们拿最近比较火的谍战片来打个比方,JSON是地下党们用来书写和交换情报的“暗号”,而JSONP则是把用暗号书写的情 报传递给自己同志时使用的接头方式。看到没?一个是描述信息的格式,一个是信息传递双方约定的方法。

  既然随便聊聊,那我们就不再采用教条的方式来讲述,而是把关注重心放在帮助开发人员理解是否应当选择使用以及如何使用上。

  什么是JSON

  前面简单说了一下,JSON是一种基于文本的数据交换方式,或者叫做数据描述格式,你是否该选用他首先肯定要关注它所拥有的优点。

JSON的优点:

  1、基于纯文本,跨平台传递极其简单;

  2、Javascript原生支持,后台语言几乎全部支持;

  3、轻量级数据格式,占用字符数量极少,特别适合互联网传递;

  4、可读性较强,虽然比不上XML那么一目了然,但在合理的依次缩进之后还是很容易识别的;

  5、容易编写和解析,当然前提是你要知道数据结构;

  JSON的缺点当然也有,但在作者看来实在是无关紧要的东西,所以不再单独说明。

JSON的格式或者叫规则:

  JSON能够以非常简单的方式来描述数据结构,XML能做的它都能做,因此在跨平台方面两者完全不分伯仲。

  1、JSON只有两种数据类型描述符,大括号{}和方括号[],其余英文冒号:是映射符,英文逗号,是分隔符,英文双引号""是定义符。

  2、大括号{}用来描述一组“不同类型的无序键值对集合”(每个键值对可以理解为OOP的属性描述),方括号[]用来描述一组“相同类型的有序数据集合”(可对应OOP的数组)。

  3、上述两种集合中若有多个子项,则通过英文逗号,进行分隔。

  4、键值对以英文冒号:进行分隔,并且建议键名都加上英文双引号”",以便于不同语言的解析。

   5、JSON内部常用数据类型无非就是字符串、数字、布尔、日期、null 这么几个,字符串必须用双引号引起来,其余的都不用,日期类型比较特殊,这里就不展开讲述了,只是建议如果客户端没有按日期排序功能需求的话,那么把日期 时间直接作为字符串传递就好,可以省去很多麻烦。

  JSON实例:

复制代码 代码如下:

// 描述一个人
var person = {
"Name": "Bob",
"Age": 32,
"Company": "IBM",
"Engineer": true
}
// 获取这个人的信息
var personAge = person.Age;
// 描述几个人
var members = [
{
"Name": "Bob",
"Age": 32,
"Company": "IBM",
"Engineer": true
},
{
"Name": "John",
"Age": 20,
"Company": "Oracle",
"Engineer": false
},
{
"Name": "Henry",
"Age": 45,
"Company": "Microsoft",
"Engineer": false
}
]
// 读取其中John的公司名称
var johnsCompany = members[1].Company;
// 描述一次会议
var conference = {
"Conference": "Future Marketing",
"Date": "2012-6-1",
"Address": "Beijing",
"Members":
[
{
"Name": "Bob",
"Age": 32,
"Company": "IBM",
"Engineer": true
},
{
"Name": "John",
"Age": 20,
"Company": "Oracle",
"Engineer": false
},
{
"Name": "Henry",
"Age": 45,
"Company": "Microsoft",
"Engineer": false
}
]
}
// 读取参会者Henry是否工程师
var henryIsAnEngineer = conference.Members[2].Engineer;


关于JSON,就说这么多,更多细节请在开发过程中查阅资料深入学习。

  什么是JSONP

  先说说JSONP是怎么产生的:

  其实网上关于JSONP的讲解有很多,但却千篇一律,而且云里雾里,对于很多刚接触的人来讲理解起来有些困难,小可不才,试着用自己的方式来阐释一下这个问题,看看是否有帮助。

  1、一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准;

  2、不过我们又发现,Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>);

  3、于是可以判断,当前阶段如果想通过纯web端(ActiveX控件、服务端代理、属于未来的HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理;

  4、恰巧我们已经知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据;

  5、这样子解决方案就呼之欲出了,web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。

  6、客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了,这种获取远程数据的方式看起来非常像AJAX,但其实并不一样。

  7、为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback 参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数 据了。

  如果对于callback参数如何使用还有些模糊的话,我们后面会有具体的实例来讲解。

  JSONP的客户端具体实现:

  不管jQuery也好,ExtJs也罢,又或者是其他支持jsonp的框架,他们幕后所做的工作都是一样的,下面我来循序渐进的说明一下jsonp在客户端的实现:

  1、我们知道,哪怕跨域js文件中的代码(当然指符合web脚本安全策略的),web页面也是可以无条件执行的。

  远程服务器remoteserver.com根目录下有个remote.js文件代码如下:

复制代码 代码如下:

alert('我是远程文件');  


本地服务器localserver.com下有个jsonp.html页面代码如下:

复制代码 代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>
<body>
</body>
</html>


毫无疑问,页面将会弹出一个提示窗体,显示跨域调用成功。

  2、现在我们在jsonp.html页面定义一个函数,然后在远程remote.js中传入数据进行调用。

  jsonp.html页面代码如下:

复制代码 代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
var localHandler = function(data){
alert('我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:' + data.result);
};
</script>
<script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>
<body>
</body>
</html>


 remote.js文件代码如下:

复制代码 代码如下:

localHandler({"result":"我是远程js带来的数据"});


运 行之后查看结果,页面成功弹出提示窗口,显示本地函数被跨域的远程js调用成功,并且还接收到了远程js带来的数据。很欣喜,跨域远程获取数据的目的基本 实现了,但是又一个问题出现了,我怎么让远程js知道它应该调用的本地函数叫什么名字呢?毕竟是jsonp的服务者都要面对很多服务对象,而这些服务对象 各自的本地函数都不相同啊?我们接着往下看。

  3、聪明的开发者很容易想到,只要服务端提供的js脚本是动态生成的就行了呗,这样调用者可以传一个参数过去告诉服务端“我想要一段调用XXX函数的js代码,请你返回给我”,于是服务器就可以按照客户端的需求来生成js脚本并响应了。

  看jsonp.html页面的代码:

复制代码 代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
// 得到航班信息查询结果后的回调函数
var flightHandler = function(data){
alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
};
// 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";
// 创建script标签,设置其属性
var script = document.createElement('script');
script.setAttribute('src', url);
// 把script标签加入head,此时调用开始
document.getElementsByTagName('head')[0].appendChild(script);
</script>
</head>
<body>
</body>
</html>


这次的代码变化比较大,不再直接把远程js文件写死,而是编码实现动态查询,而这也正是jsonp客户端实现的核心部分,本例中的重点也就在于如何完成jsonp调用的全过程。

  我们看到调用的url中传递了一个code参数,告诉服务器我要查的是CA1998次航班的信息,而callback参数则告诉服务器,我的本地回调函数叫做flightHandler,所以请把查询结果传入这个函数中进行调用。

  OK,服务器很聪明,这个叫做flightResult.aspx的页面生成了一段这样的代码提供给jsonp.html(服务端的实现这里就不演示了,与你选用的语言无关,说到底就是拼接字符串):

复制代码 代码如下:

flightHandler({
"code": "CA1998",
"price": 1780,
"tickets": 5
});  


我们看到,传递给flightHandler函数的是一个json,它描述了航班的基本信息。运行一下页面,成功弹出提示窗口,jsonp的执行全过程顺利完成!

  4、到这里为止的话,相信你已经能够理解jsonp的客户端实现原理了吧?剩下的就是如何把代码封装一下,以便于与用户界面交互,从而实现多次和重复调用。

  什么?你用的是jQuery,想知道jQuery如何实现jsonp调用?好吧,那我就好人做到底,再给你一段jQuery使用jsonp的代码(我们依然沿用上面那个航班信息查询的例子,假定返回jsonp结果不变):

复制代码 代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Untitled Page</title>
<script type="text/javascript" src=jquery.min.js"></script>
<script type="text/javascript">
jQuery(document).ready(function(){
$.ajax({
type: "get",
async: false,
url: "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998",
dataType: "jsonp",
jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
success: function(json){
alert('您查询到航班信息:票价: ' + json.price + ' 元,余票: ' + json.tickets + ' 张。');
},
error: function(){
alert('fail');
}
});
});
</script>
</head>
<body>
</body>
</html>


是 不是有点奇怪?为什么我这次没有写flightHandler这个函数呢?而且竟然也运行成功了!哈哈,这就是jQuery的功劳了,jquery在处理 jsonp类型的ajax时(还是忍不住吐槽,虽然jquery也把jsonp归入了ajax,但其实它们真的不是一回事儿),自动帮你生成回调函数并把 数据取出来供success属性方法来调用,是不是很爽呀?

 
分享到:
评论

相关推荐

    jsonp跨域请求数据实现手机号码查询实例分析

    之前一篇《说说JSON和JSONP 也许你会豁然开朗》对jsonp已经介绍的很详细了,这里就不多介绍了,直接上实例吧 代码: &lt;!DOCTYPE HTML&gt; &lt;html&gt; &lt;head&gt; &lt;meta charset=utf-8 /&gt; &lt;meta name=...

    深入分析jsonp协议原理

    今天在开发联调的过程中,需要跨域的获取数据,因为使用的jquery,当然使用dataType:’jsonp’就能够很easy的解决了。...JSON和JSONP虽然只有一个字母的差别,但其实他们根本不是一回事儿:JSON是一种数据交换格

    呼伦贝尔市-扎兰屯市-街道行政区划_150783_Shp数据-wgs84坐标系.rar

    呼伦贝尔市-扎兰屯市-街道行政区划_150783_Shp数据-wgs84坐标系.rar

    text13届真题二.zip

    text13届真题二.zip

    锡林郭勒盟-东乌珠穆沁旗-街道行政区划_152525_Shp数据-wgs84坐标系.rar

    街道级行政区划shp矢量数据,wgs84坐标系,下载直接使用

    WPF实现工业级动态流体管道动画:C#代码解析与性能优化

    内容概要:本文详细介绍了如何使用WPF(Windows Presentation Foundation)实现逼真的工业组态软件中的流体管道动画。主要内容涵盖管道绘制、流体动画效果、动态速度控制以及性能优化等方面。首先,通过C#代码展示了如何使用几何图形和颜色动画创建动态变化的管道。接着,引入粒子系统和模糊效果来增强流体的真实感。为了实现流体速度的动态调整,文中提供了流速控制器的实现方法。此外,还讨论了基于帧刷新的性能优化技术和双重缓冲机制的应用。最后,文章提到了一些高级技巧,如Perlin噪声生成流速波动、粒子沿曲线运动、动态纹理等。 适合人群:对WPF开发感兴趣的中级及以上水平的开发者,尤其是那些希望深入了解WPF图形和动画特性的程序员。 使用场景及目标:适用于需要开发工业组态软件或其他涉及流体模拟应用的项目。主要目标是帮助开发者掌握如何使用WPF创建高效且视觉效果出色的流体动画。 其他说明:文中提供的代码片段可以直接应用于实际项目中,同时也鼓励读者进一步探索更多复杂的流体模拟技术。

    HCIA-Datacom高阶:vlan、vlanif、单臂路由、静态路由、ospf综合实验

    HCIA-Datacom高阶:vlan、vlanif、单臂路由、静态路由、ospf综合实验

    毕业论文 基于fpga的rs 232串口通讯逻辑设计说明书.doc

    毕业论文 基于fpga的rs 232串口通讯逻辑设计说明书.doc

    呼伦贝尔市-阿荣旗-街道行政区划_150721_Shp数据-wgs84坐标系.rar

    呼伦贝尔市-阿荣旗-街道行政区划_150721_Shp数据-wgs84坐标系.rar

    微电网能源管理中的随机博弈与Python实现:基于双网络架构的动态定价与负荷调度

    内容概要:本文详细介绍了微电网中能源管理的随机博弈模型及其Python实现。首先,通过构建MicrogridEnv类来模拟多方博弈环境,每个智能体可以进行买卖操作并调整负荷。接着,引入了ET网络用于处理价格博弈,ADL网络用于负荷预测。这两个网络通过策略梯度协同优化,共同实现动态定价和负载调度。文中展示了具体的训练过程和实验结果,证明了该模型在波动环境下能够显著提高系统收益稳定性。此外,还讨论了动态定价策略的具体实现,包括供需平衡系数计算和价格波动修正项的设计。最后,通过多智能体交互代码展示了真实的博弈过程,并进行了对比实验,验证了模型的有效性和优越性。 适合人群:对微电网能源管理和强化学习感兴趣的科研人员、工程师和技术爱好者。 使用场景及目标:适用于研究和开发微电网能源管理系统,旨在通过动态定价和负荷调度优化能源利用效率,提高系统收益和稳定性。 其他说明:本文不仅提供了详细的代码实现,还深入探讨了模型背后的理论依据和设计思路,帮助读者全面理解微电网能源管理中的随机博弈机制。

    皮秒分辨率的FPGA TDC技术研究.pdf

    皮秒分辨率的FPGA TDC技术研究.pdf

    【Java Web开发】Tomcat服务器配置与优化:面试专题及性能调优详解Tomcat服务器的

    内容概要:本文档《Tomcat面试专题及答案.pdf》详细介绍了Tomcat服务器的相关知识点,涵盖配置、优化、部署、内存与垃圾回收调优、Session处理、JMS远程监控、专业分析工具、Session数目查看、内存使用情况监视、类加载与对象回收情况打印以及Tomcat的工作模式。文档首先讲解了Tomcat的默认端口及修改方法,随后深入探讨了四种Connector运行模式(bio、nio、aio、apr)及其参数配置。接着介绍了三种Web应用部署方式,并阐述了Tomcat容器创建Servlet实例的原理。在优化部分,重点讨论了连接配置、内存调优、垃圾回收策略的选择,还涉及了共享Session的多种处理方案。最后,文档概述了一个HTTP请求在Tomcat内部的完整处理流程。 适合人群:有一定Java开发经验,特别是Web开发背景的研发人员和技术专家。 使用场景及目标:①准备技术面试,尤其是针对Tomcat相关问题;②优化现有基于Tomcat的应用系统性能;③深入了解Tomcat架构及其工作原理,以更好地进行应用部署和维护。 其他说明:文档内容详实,既适合初学者入门学习,也适合有一定经验的开发者深入研究。建议读者在实际工作中结合自身环境进行针对性配置与优化实践。

    软考中级-软件设计师知识点整理(一篇就过(3).html

    软考中级-软件设计师知识点整理(一篇就过(3).html

    MATLAB数据预测:融合多种机器学习与统计模型的时间序列预测方法

    内容概要:本文详细介绍了使用MATLAB进行数据预测的各种方法和技术细节,涵盖了现代的人工智能算法如LSTM、BP神经网络、RBF和Elman等,以及传统的统计方法如ARIMA和GM灰色预测。文中不仅提供了具体的代码实例,还分享了许多实用的经验和注意事项,强调了数据预处理的重要性。作者通过多个实际案例展示了不同算法在不同数据集上的表现差异,指出了选择合适算法的关键在于理解数据本身的特性。 适合人群:对时间序列预测感兴趣的科研人员、工程师以及有一定编程基础并希望深入理解MATLAB预测工具的学生。 使用场景及目标:适用于需要进行时间序列数据分析和预测的研究项目,旨在帮助读者掌握如何根据具体应用场景选择最合适的预测模型,并能够独立完成从数据准备到模型评估的全过程。 其他说明:文章特别提醒读者,在面对复杂多变的实际问题时,除了关注算法本身外,更要重视数据的质量和预处理步骤。此外,作者还提供了一些关于模型调优的小贴士,如调整LSTM层数、设置ARIMA参数等。

    沧州市-吴桥县--街道行政区划_130928_Shp-wgs84坐标系.rar

    街道级行政区划shp数据,wgs84坐标系,直接使用。

    流水线贴膜机:基于PLC与触摸屏的工业自动化控制及运动控制初学者指南

    内容概要:本文详细介绍了流水线贴膜机的控制系统设计,涵盖PLC与触摸屏的协同控制。具体包括上下气缸、夹紧气缸、输送带电机、贴膜伺服和旋转电机的控制逻辑。PLC程序实现了各部件的协调运作,而触摸屏提供了友好操作界面。文中不仅展示了完整的程序结构和关键代码片段,还分享了许多实际调试经验和常见问题解决方案。 适合人群:对工业自动化控制感兴趣的初学者,尤其是想要深入了解PLC编程和运动控制的技术人员。 使用场景及目标:适用于学习PLC编程、触摸屏设计、气缸和电机控制、伺服定位等基础知识。通过该项目,学习者可以掌握工业自动化系统的完整开发流程,理解各组件间的协作机制,并积累实际调试经验。 其他说明:项目支持博图V15.1及以上版本,强调模块化设计和良好的代码规范,有助于提高程序的可维护性和扩展性。文中提供的实例和技巧能够帮助初学者更好地理解和应用工业自动化控制技术。

    工业级激光雷达SLAM三维建图:基于点云算法与高精度云台系统的创新应用

    内容概要:本文详细介绍了自主研发的工业级三维扫描系统,该系统利用二维激光雷达与高精度单轴云台相结合,实现了高效、精准的三维点云建模。文章重点阐述了云台控制、数据同步、点云重建、滤波算法以及多雷达适配等方面的技术细节。云台控制系统采用裸机驱动程序,确保角度定位误差小于0.03度;数据同步方面,通过时间戳双缓冲机制和优化的时间对齐算法,提高了数据处理速度;点云重建部分,提出了改进的坐标转换矩阵,显著提升了重建精度;针对工业环境的特点,开发了多种滤波算法,有效去除噪点;此外,系统支持多种雷达的动态配置,增强了灵活性和适应性。 适合人群:从事激光雷达SLAM研究、三维建图、工业自动化领域的研究人员和技术人员。 使用场景及目标:适用于矿山、冶金、建筑等复杂工业环境中的三维数据获取和建模任务,旨在提高测绘效率和精度,降低设备成本,增强系统的鲁棒性和可靠性。 其他说明:文中提供了大量的代码片段和实际应用场景案例,强调了技术创新和实用性的结合,展现了从硬件设计到软件算法的全面解决方案。

    海洋气候与海洋生物数据集

    观测日期 位置 海洋位置名称(例如,马尔代夫大堡礁) 纬度 观测点纬度 经度 观测点经度 海温(°C) 海面温度(摄氏度) pH值 海水的酸度(较低意味着酸性更强,这是酸化的标志) 漂白严重程度 分类变量:无、低、中、高 观察到的物种 采样期间观察到的海洋物种数量 海洋热浪 布尔标志(真/假),指示SST是否>30°C 随着气候变化的加速,世界海洋正在经历重大变革。该数据集汇编了海面温度(SST)、pH值、珊瑚白化严重程度和生态关键海洋区物种观测的合成但真实的测量结果。它涵盖了2015年至2023年,模拟了海洋环境如何应对全球变暖、酸化和热浪。 该数据集的目标是支持机器学习、气候分析和生态建模

    邢台市-信都区--街道行政区划_130503_Shp-wgs84坐标系.rar

    街道级行政区划shp数据,wgs84坐标系,直接下载使用。

Global site tag (gtag.js) - Google Analytics