浅析json与jsonp区别及通过ajax获得json数据后格式的转换


 有关json与jsonp的区别(json才是目的,jsonp只是手段)介绍如下所示:

一言以蔽之,json返回的是一串数据;而jsonp返回的是脚本代码(包含一个函数调用);

JSON其实就是JavaScript中的一个对象,跟var obj={}在质上完全一样,只是在量上可以无限扩展。简单地讲,json其实就是JavaScript中的对象(Object)和数组(Array,其实也是对象)这倆好基友在那儿你嵌我我嵌你地套上n多层,以此模拟出许多复杂的数据结构。

json易于人阅读和编写,也易于机器解析和生成,相对网络传输速率较高,功能型网站前后端往往要频繁大量交换数据,而json凭借其强大的表现力和高颜值渐渐地成为理想的前后端数据交换语言。那xml前辈呢,我觉得应该会像微软的xp那样功成身退。

同源(不懂同源策略的童鞋请自行百度)下的前后端数据交换格式确定使用json了,那么问题来了,如果我想获取别人网站上提供的数据肿么做到呢?也就是跨域读取数据问题(不要钻牛角说你不需要读取其他网站的数据,相信我,你早晚得需要),json行不行呢?答案是No Way,为什么呢,因为json只是普通的文本格式,能让你这样就轻松拿到那服务端就没有任何安全和保密性可言了,这样的话互联网世界非乱套不可,这个问题那些牛X的规范制定者早就想到了,所以使用了同源策略来限制文件获取。最后的结果就是只有像img、script、iframe这类可以指定src属性的标签有跨域获取别人网站上数据(图片,脚本,源文件其实都是数据)的能力。比如:

<!--京东商品图片-->
<img src="http://img30.360buyimg.com/jgsq-productsoa/jfs/t2407/323/1635505465/47386/f2d89d88/56615e00N7a475ee6.jpg" />
<!--百度CDN-->
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script> 

看来直接获取json是行不通了,那有没有其他方法能拿到数据呢?于是乎jsonp就这样被聪明的开发者给发现了,为什么说是发现而不是发明呢,因为并没有涉及到任何新技术,就像发现ajax一样。

jsonp原理是这样的,网站A需要获取网站B的数据,网站B说我给你们一个方法,【1. 你们使用<script src="http://www.B.com/open.js"></script>标签先获取到open.js文件(网站B的责任),这里边有你们需要的数据。2. 你们获取数据后处理数据(总得处理数据吧)的方法名必须命名为foo(数据请求者的责任和义务)】,这里相当于B网站和请求获取数据者之间建立了一个协议,要求请求者务必按照规则办事,如果请求者不能同时遵守上面两条就不能按预期获取数据。额..,这也算相当于建立了一个潜规则吧

open.js内容

foo({"name":"B","age":23});  //为什么不直接写成json数据{"name":"B","age":23}呢,原因很简单,在js文件总得合乎js语法吧
//这也是为什么协议中明确规定处理数据的方法名必须命名为foo,因为B网站是在假定请求者的脚本中已经定义了数据处理方法foo的情况下返回数据;
//不然就会报foo is not defined错误

网站A脚本须有

function foo(data){
console.log(data);
//ToDo.. 
} 

啊!虽然拐了个弯,但数据总算得到了,网站A,网站B都非常高兴,那么问题又来了,网站C说也需要获取网站B的数据,网站B把协议甩给它,网站C拿过来一看,草泥马啊,foo这个名字已经在自己的脚本文件的6868行用过了,而且已经使用在脚本的各个角落,批量替换会导致很多潜在bug啊,网站B情急之下决定把foo改成fool,网站A立马蹦起来,因为自己的网站已经在很多地方使用foo引用了数据。

为了避免上面情况发生,那些牛X哄哄的开发者使用了动态生成js文件的方法,php版本如下:

open.php

<?php
header('Content-type: application/javascript');
$jsonCallback = htmlspecialchars($_REQUEST ['callback']); //获取请求者自定义的回调函数名
$jsonData ='{"name":"B","age":23}'; //待返回的json数据
echo $jsonCallback . "(" . $jsonData . ")"; //输出jsonp格式的数据,即一行函数调用语句
?> 

额 ..,至于php为什么能返回js格式文件,自行百度。

于是网站A用<script src="http://www.B.com/open.php?callback=foo"></script>来请求数据,不需要修改任何变量,返回给A的脚本文件内容是:

foo({"name":"B","age":23}); //所谓的jsonp,就是一句函数调用,数据都被包裹传递到参数中了,千万别穿个马甲就不认识了 
网站C就用<script src="http://www.B.com/open.php?callback=blah"></script>来请求数据,返回给C的脚本文件内容是:
blah({"name":"B","age":23}); 
网站N就用<script src="http://www.B.com/open.php?callback=what"></script>来请求数据,返回给N的脚本文件内容是:
what({"name":"B","age":23}); 

Problem Solved,大家都取到了期望的数据,并且避免了命名冲突。

jsonp全名叫做json with padding,很形象,就是把json对象用符合js语法的形式包裹起来以使其它网站可以请求得到,也就是将json数据封装成js文件;

json是理想的数据交换格式,但没办法跨域直接获取,于是就将json包裹(padding)在一个合法的js语句中作为js文件传过去。这就是json和jsonp的区别,json是想要的东西,jsonp是达到这个目的而普遍采用的一种方法,当然最终获得和处理的还是json。所以说json是目的,jsonp只是手段。json总会用到,而jsonp只有在跨域获取数据才会用到。

理解了json和jsonp的区别之后,其实ajax里的跨域获取数据就很好理解和实现了,同源时候并没有什么特别的,直接取就行,跨域时候需要拐个弯来达到目的。

附上jquery中ajax请求json数据实例:

(同源):

$.ajax({
url:"persons.json",
success:function(data){
    console.log(data);
     //ToDo..
  }
}); 

(跨域):

$.ajax({
url:"http://www.B.com/open.php?callback=?",
dataType:"jsonp",
success:function(data){
console.log(data);
//ToDo..
}
}); 

jquery已把jsonp封装进ajax,很合理,因为毕竟绝大多数的jsonp请求都是ajax,关于jquery的ajax具体用法请自行百度,另外要注意的一点就是不同的网站提供的数据接口的$_REQUEST ['callback']中不一定绝对是callback也可能是cb,cbk等,具体使用时务必阅读服务端提供的有关接口使用的详细文档。

下面给大家介绍下由“夜未央0906”写的通过ajax获得json数据后格式的转换

在有些情况下获取到的json数据可能是string类型的,需要把其格式化为json对象才方便解析。

a)原生js通过ajax获取到的json

  此时返回的数据默认是string型的,所以需要用eval()函数将其转化为json对象。需要注意函数内字符串的格式:eval(“(” + data+“)”),因为返回的string是在{}里面的,eval会将大括号识别为js代码块开始和结束的标志,所以必须加上(),将其强制转化为对象来处理。

b)jquery获取

  1:通过ajax()异步请求并把type设置为json,返回的就是json对象。

  2:通过用与ajax()等价的$.getJSON(url,data1,function(data2,status,xhr){//......})方法获取的也是json对象。其中data1为连同请求发送的数据,data2为服务器返回的数据即json对象。



相关阅读:
用HTML5实现手机摇一摇的功能的教程
js实现鼠标感应向下滑动隐藏菜单的方法
Android下拉刷新控件SwipeRefreshLayout源码解析
PHP实现将MySQL重复ID二维数组重组为三维数组的方法
C#调用mmpeg进行各种视频转换的类实例
深入解析Java编程中的boolean对象的运用
php简单判断文本编码的方法
Javascript中引用示例介绍
JS上传图片前实现图片预览效果的方法
Mac怎么删除客人用户?苹果mac关闭/禁用客人用户方法介绍
PHP获取MSN好友列表类的实现代码
php去除字符串中空字符的常用方法小结
更高效的使用JQuery 这里总结了8个小技巧
php数组冒泡排序算法实例
快速导航
PHP MySQL HTML CSS JavaScript MSSQL AJAX .NET JSP Linux Mac ASP 服务器 SQL jQuery C# C++ java Android IOS oracle MongoDB SQLite wamp 交通频道 作文范文 滦河沿-二道沟门 辽阳-陶赖昭 西安南-秦皇岛 西安南-呼和浩特 朝阳地-滦平 土牧尔台-巴彦郭勒 福州-黄石 肇庆-汨罗 葫芦岛-白城 临沂-平邑 黄冈-荆州 漳平-义乌 北兴安-南兴安 汉源-元谋 松树镇-枕头峰 石人城-一面坡 遵义-黎塘 西柳-沈阳北 公主埂-宝木吐 武山-邢台 忻州-高平 呼和浩特东-三门峡 六安-桐柏 余粮堡-张家口南 中宁-安口窑 草河口-林家台 梧州-道州 绍兴东-兴安北 朱家沟-佳木斯 古田会址-瑞安 高平-武昌 白洋淀-关林 融水-襄阳 丰都-徐州东 灵宝-株洲 乌鲁木齐-林东 杭州东-宁波 庐山-东胜西 河唇-南宁东 谷城-石泉县 克山-海北 衡阳-东莞 黎塘-上饶 大平房-叶柏寿 上海-共青城 秧草地-威箐 铜陵-安庆 沂南-五莲 衡阳东-淮南东 民权-无锡 尚志-大民屯 义乌-黔江 商丘-长治北 南平南-台前 郑州东-新余北 扎兰屯-汤原 保定-汝州 柴河-尚志 西平-济宁 山海关-潢川 襄阳东-成都 盖州西-盘锦北 尚志-吴桥 霸州-庐山 襄阳-佛山 丹阳-襄阳东 牡丹江-大杨树东 淄博-柳河 大民屯-金州 兰考南-渑池南 龙江-昌黎 锦州-济南东 邵阳-湘乡 任丘-连云港东 温州南-三明北 许昌-金昌 柳州-长兴 田家沟-三十家 玉门-兰州西 青州市-界首市 从枣庄到威海寄信贴多大面值的邮票
乐清虹桥到雁荡山火车列车站多久
今年春节从中山到温州的列车票
500 公里从苏州到安庆回家过年 ,驾车需要注意哪些谢谢啦
2011亳州药交会到哪里住旅店最好最实惠我是南京的 谢谢
从汕头到大连用ems需要多少小时
汉朝时期的官职简表
重庆飞机场到重庆火车列车站有多远!可以坐什么车到火车列车站
合肥到盐城的客车有吗?
内江到广州火车列车售票时间
从上海列车火车站到复旦大学附件的复宣酒店乘几路公交车打车大
侯马到乌鲁木齐坐列车火车怎么转车
从晋江怎么搭公车到泉州展览城
我要从南昌自驾车到烟台。请问最佳路线怎么坐车?
我想问下 这个月28号从秦皇岛买列车火车票去葫芦岛 买动车会没票么
商丘到淮阳客车汽车多少钱
太仓到无锡要多久
大同村官体检时间
宣武区915车站
滨州到青岛的车有几点的,到哪个车站
东莞到贵阳市该怎么坐车
邯郸火车下了怎么去科信学院
我朋友现在正坐汽车往沧州走,大概8点半左到沧州火车站请问此
2011河北移动(石家庄)放心回家什么时候开始怎么办理
嘉鱼到赤壁要多少小时
乌鲁木齐到北京需要几小时
东山到苏州卫生职业技术学院的公交路线
从唐山市坐火车列车到邯郸需要几个小时
从大连港到丹东如何坐汽车车
池州贵池下起了大雪很冷,怎么拍婚纱照外景

Copyright © 2016 phpStudy |