json
基本概念
- JSON 是轻量级的文本数据交换格式
- Javascript原生支持,后台语言几乎全部支持
- 容易编写和解析
格式和规则
- JSON只有两种数据类型描述符,大括号{}和方括号[],其余英文冒号:是映射符,英文逗号,是分隔符,英文双引号""是定义符
- 大括号{}用来描述一组“不同类型的无序键值对集合”(每个键值对可以理解为OOP的属性描述),方括号[]用来描述一组“相同类型的有序数据集合”(可对应OOP的数组)
- 上述两种集合中若有多个子项,则通过英文逗号,进行分隔
- 键值对以英文冒号:进行分隔,并且建议键名都加上英文双引号"",以便于不同语言的解析
- JSON内部常用数据类型无非就是字符串、数字、布尔、日期、null 这么几个,字符串必须用双引号引起来,其余的都不用
实例
{
"sites": [
{ "name":"百度" , "url":"www.baidu.com" },
{ "name":"Bing" , "url":"www.bing.com" },
]
}
jsonp
jsonp的起源
要讨论jsonp是如何产生的就离不开浏览器的同源策略,那么什么是同源策略呢。
同源指的是协议,主机(IP)以及端口相同,通过下面的表格能够比较直观的了解同源的判断规则。
以http://example.com/test/dir1为例
URL | 结果 | 原因 |
---|---|---|
http://example.com/test/dir2 | 同源 | 只有路径不同 |
http://example.com/ | 同源 | 只有路径不同 |
http://example.com:81/tset | 不同源 | 端口不同 |
https://example.com/tset | 不同源 | 协议不同(https) |
http://en.example.com | 不同源 | 主机不同 |
在同源策略的约束下,一个页面的脚本不可以访问不同源页面的资源。这个策略可以阻止一个页面上的恶意脚本通过页面的DOM对象获得访问另一个页面上敏感信息的权限。设想一下如果没有同源策略,你在访问恶意网站evil.com同时也在访问网银的页面,evil页面上的js脚本就可以访问到网银页面的资源例如Dom对象,可能会窃取cookie发送至攻击者服务器导致财产损失,所以同源策略可以看做现代浏览器安全的基石。
但同源策略在保护页面的前提下也牺牲了网页的拓展性,如果是稍微大一些的应用就很难把html,js,css,图片等资源完全放置在同一台服务器上。所以现在浏览器在例如img,script,style等有src属性的标签中允许去引用跨域的资源。因为script可以跨域读取js在浏览器执行,又由于json被js原生支持于是jsonp就诞生了。
jsonp的过程
jsonp用一句话概括就是定义好callback(回调函数)并传送至服务端,服务端采用callback为函数名包裹json数据返回浏览器并执行。
可能只说明定义还是不太好理解,下面用几个实例来进一步阐述这个过程。
jsonp代码实例
下面精彩举例来自于随便说说json和jsonp
远端js可以执行
首先远端的js代码在浏览器中被加载是可以正常执行的,即js文件的域是加载页面所处的域而不是储存js文件的域!!!
服务端js代码:(remote.com/remote.js)
alert('remote data')
用户浏览器中js代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script type="text/javascript" src="http://remote.com/remote.js"></script>
</body>
</html>
此代码会正常弹窗
回调函数执行
然后我们在客户端页面中加入一个回调函数
用户浏览器中js代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
var callback = function (data){
alert('我是本地函数 被服务端传来的函数调用 远程js带来的数据是' + data.result)
}
</script>
<script type="text/javascript" src="http://remote.com/remote.js"></script>
</body>
</html>
服务端js代码:
callback({"result":"我是远程js带来的数据"});
运行后发现正常弹窗 服务端的数据被带来前端且正常调用了客户端定义的回调函数,此时跨域获取数据的目的终于实现,最后一个问题,如何让服务端知道该调用的客户端函数名字叫什么,解决办法就是将回调函数名传给客户端.。
服务端动态调用回调函数
此时用户浏览器的代码变为:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
var callbackName = function (data){
alert('我是本地函数 被服务端传来的函数调用 远程js带来的数据是' + data.result)
}
</script>
<script type="text/javascript" src="http://remote.com/remote.js?callback=callbackName"></script>
</body>
</html>
此时远程服务器上运行的代码会接受客户端传来的请求,提取出callback的名字,将查询数据封装为
callbackName(
{远程数据}
)
运行后浏览器收到了服务端的数据且执行callbackName函数。
客户端动态生成js标签
一般情况下,我们希望这个script标签能够动态的调用,而不是像上面因为固定在html里面所以没等页面显示就执行了,很不灵活。我们可以通过javascript动态的创建script标签,这样我们就可以灵活调用远程服务了。
客户端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>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>
远程服务器返回的数据形式:
flightHandler({
"code": "CA1998",
"price": 1780,
"tickets": 5
});
此时就完成了完整的远程资源调用,客户端可以定义一个形如提交查询航班信息的button绑定动态添加js的函数。用户输入航班信息后动态生成一个js标签,访问带有航班信息的服务器,获得数据后返回callback包裹的航班信息到客户端,客户端执行callback弹出航班的价格。
参考文章:
说说json和jsonp