浅析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 服务器 CMS SQL jQuery C# C++ java Android IOS oracle MongoDB PostgreSQL SQLite 交通频道 上林公路汽车客运服务中心 广西壮族自治区南宁市上林县
岳阳县汽车站 汽车运输总公司
安康高速客运汽车站停车场 陕西省安康市汉滨区
善堂客运站 河南省鹤壁市浚县
蟠龙客运站 陕西省宝鸡市金台区
县河车站 湖北省十堰市竹溪县
黄龙汽车客运站 四川省广元市元坝区
东兴乡客运站 黑龙江省大庆市林甸县
格林豪泰酒店(海安汽车站快捷店) 江苏省南通市海安县通榆中路46号
三屯乡汽车站 河南省洛阳市汝阳县
沪铁长途客运站 恒丰路783、785号
许昌县榆林乡汽车客运站 河南省许昌市许昌县
浯口客运站 湖南省岳阳市平江县
贵溪市汽车站 江西省鹰潭市贵溪市
南平汽车站车出入口 福建省南平市延平区
犍为芭沟汽车站 四川省乐山市犍为县
泰山汽车东站候车大厅 山东省泰安市泰山区
石佛客运站 新石线
楚雄东华客运站 云南省楚雄彝族自治州楚雄市
成大方圆连锁药店客运站分店 辽宁省盘锦市双台子区
东张孟乡客运站 河北省邯郸市广平县
平乡汽车站 三二五省道
榆中夏官营汽车站 甘肃省兰州市榆中县
岑溪市汽车客运服务站 广西壮族自治区.梧州市岑溪市玉梧大道80号
深州汽车站 永平大街
石楼客运站 四川省南充市嘉陵区
新乡汽车客运总站 自由路155号
随州洪山车站 湖北省随州市曾都区
廉村乡客运站 河南省平顶山市叶县
惠州河南岸汽车站 河南岸惠淡公路苏屋墩街三环路口货运站
德惠公路客运站 对站街与德惠路交汇处
日照汽车东站 黄海二路
公主岭和气客运站 和气卫生院对面
新桥客运站 河南省周口市项城市
丹阳汽车东站 中山路
翟镇汽车站 河南省洛阳市偃师市
郧县清凉寺客运站 湖北省十堰市郧县
星子客运汽车站 江西省九江市星子县
赵县范庄客运站 河北省石家庄市赵县
罗河长途客运中心 安徽省巢湖市庐江县
小芝客运站 浙江省台州市临海市
邛崃回龙客运站 四川省成都市邛崃市
凌海高峰客运站 辽宁省锦州市凌海市
琴溪客运站 三二二省道
紫金县水墩客运站 广东省河源市紫金县
柳城临时客运站 城东路
梓潼黎雅客运站 三零二省道
普洱客运站 振兴大道148
睢县平岗客运站 河南省商丘市睢县
大丰南汽车站 金丰南大街
长垣县佘家乡客运站 河南省新乡市长垣县
蚌谷乡汽车客运站 云南省文山壮族苗族自治州西畴县
克山公路客运站 黑龙江省齐齐哈尔市克山县
榆中贡井乡汽车站 甘肃省兰州市榆中县
佛山南海车站 佛平二路
武清崔黄口客运站 天津市武清区
客运站旅馆 山东省潍坊市安丘市
新城汽车站 河北省保定市高碑店市
长汀策武客运站 福建省龙岩市长汀县
长春长途汽车北站 宽城区长白路24号
荆门万里交通集团客运站 白云大道39号
鄢陵彭店汽车站 河南省许昌市鄢陵县
武陟三阳客运站 河南省焦作市武陟县
黄圩客运站 江苏省盐城市响水县
新正市汽车站售票厅 河南省郑州市新郑市
嘉祥卧龙山客运站 山东省济宁市嘉祥县
五台豆村汽车客运站 山西省忻州市五台县
阳原汽车站 河北省张家口市阳原县
扎鲁特旗鲁北客运站 内蒙古自治区通辽市扎鲁特旗
阿鲁科尔沁旗天山汽车站 内蒙古自治区赤峰市阿鲁科尔沁旗
东光汽车站 火车站北侧
沅陵筲箕湾汽车站 湖南省怀化市沅陵县
恒升客运站 四川省广安市广安区
前童客运站 浙江省宁波市宁海县
珠海香洲长途站 紫荆路
盐城五星客运总站停车场 江苏省盐城市亭湖区
电白那霍客运站 广东省茂名市电白县
邻水袁市车站 四川省广安市邻水县
良村车站 河北省石家庄市裕华区
镇康凤尾客运站 云南省临沧市镇康县
临县安业客运站 山西省吕梁市临县
九三八路公交车香河总站 新华大街
中牟县冯堂客运站 河南省郑州市中牟县
佳木斯公路客运枢纽站 顺和街128
潼关秦东汽车站 陕西省渭南市潼关县
南宁金桥客运站 昆仑大道368号
交城汽车站 山西省吕梁市交城县
三口农村客运站 湖南省长沙市浏阳市
自来桥车站 零一一县道
永川花桥汽车站 重庆市永川区
固始县行政服务中心交通中心 河南省信阳市固始县
新泰新龙车站 山东省泰安市新泰市
常德市丹阳路汽车站 湖南省常德市武陵区
耿车客运站 江苏省宿迁市宿城区
南江上两客运站 四川省巴中市南江县
沙沟客运中心 江苏省泰州市兴化市
临猗汽车站 山西省运城市临猗县
客运中心站售票处 东大街9号
武陟木城镇汽车客运站 红旗路与朝阳一路交叉口向南150米路西
高州分界客运站 广东省茂名市高州市

Copyright © 2016 phpStudy |