JSON 与 JSONP
JSON (JavaScript Object Notation) is a lightweight data-interchange format. 即 JSON 是一种轻量级的数据交换格式。
1. JSON 的结构
JSON 构建于于两种(除去简单值)结构(JSON is built on two structures)
① 对象:名称(键) / 值对的集合(A collection of name / value pairs):
{
"key1": "value1",
"key2": "value2"
}
或者
{
"name": "dee",
"age": ,
"stack": {
"frontend": "JavaScript",
"backend": "php"
}
}
说明:
一个对象以 { 开始,} 结束。每个名称(name)后跟一个 :
每个键值对之间使用 , 分隔
注意:JSON 对象属性里的非数字型键值必须要加双引号,不能不加或者加单引号。
② 数组:值(value)的有序集合(An array is an ordered collection of values)
类似于 JavaScript 中的数组:
["dee", , "developer"]
把对象和数组结合起来,可以构建更复杂的数据集合:
[
{
"title": "PHP Cookbook",
"authors": [
"Sklar",
"Adam"
],
"edition":
},
{
"title": "Modern PHP",
"authors": "Lockhart"
}
]
说明:
一个数组以 [ 开始,] 结束。值之间使用 , 分隔。
值(value)可以是字符串(string)、数值(number)、true
、false
、 null
、对象(object)或者数组(array)。这些结构可以嵌套。字符串类型的值必须双引号括起来。
2. JavaScript 解析和序列化 JSON
解析:把 JSON 字符串转换为 JavaScript 对象
序列化: 把Javascript 对象转换为 JSON 字符串
JSON 流行的原因除了与 JavaScript 类似的语法,还有一个原因就是可以把 JSON 数据结构解析为 JavaScript 对象。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script>
// JavaScript 对象
var book = [
{
"title": "PHP Cookbook",
"authors": [
"Sklar",
"Adam"
],
"edition": 3
},
{
"title": "Modern PHP",
"authors": "Lockhart"
}
];
console.log(book); // 把 JavaScript 序列化为 JSON 字符串
var jsonText = JSON.stringify(book);
console.log(jsonText); // 把 JSON 字符串解析为 JavaScript 对象
var bookCopy = JSON.parse(jsonText);
console.log(bookCopy); // 旧版本浏览器使用 eval() 函数解析 JSON 字符串为 JavaScript 对象
// 结果和使用 JSON.parse() 一样
var bookCopy_ = eval(jsonText);
console.log(bookCopy_); </script>
</head>
<body> </body>
</html>
结果如下(FireFox 44.0.2):
3. jQuery 和 Ajax 获取与发送 JSON
① 获取 JSON 数据
客户端 json.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script>
<script>
$.ajax({
url: "index.php",
type: "post",
dataType: "json", // 表明接收的返回值是 JSON 格式的
data: {
"name": "dee",
"job": "developer"
},
success: function(data) {
console.log(data);
$.each(data.stack, function(name, value) {
console.log(value);
});
},
error: function() {
console.log("error");
}
});
</script>
</head>
<body> </body>
</html>
服务器端 index.php
<?php if(isset($_POST['name']) && $_POST['name'] == 'dee') { $data['code'] = 200;
$data['message'] = 'success';
$data['stack']['frontend'] = ['html', 'css', 'javascript'];
$data['stack']['backend'] = ['php', 'mysql', 'nosql', 'linux', 'node.js']; header('content-type:text/json');
exit(json_encode($data));
}
输出:
说明:在服务端写 API 接口的时候,如果是以 JSON 作为数据交换格式,要加上:
header('content-type:text/json');
此时接收到数据的客户端接受到的数据已经是一个 JavaScript 对象,不需要再做任何的解析工作,jQuery 已经自动把 JSON 字符串转换为了 JSON 对象。
在客户端接收以 JSON 为数据交换格式的 API 接口返回的数据时,也要加上:
dataType: "json",
表明接收的返回值是 JSON 格式的。
② 发送 JSON 数据
客户端 json2.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script>
</head>
<body>
<form>
<table>
<tr>
<td>name:</td>
<td><input name="name" type="text"></td>
</tr>
<tr>
<td>job:</td>
<td><input type="text" name="job"></td>
</tr>
<tr>
<td clospan="2">
<input type="button" id="submit" value="submit">
</td>
</tr>
</table>
</form>
</body>
<script>
$('#submit').click(function(){
$.ajax({
url: "index2.php",
type: "post",
contentType: "application/json",
data: JSON.stringify($('form').serializeArray()),
dataType: "json",
success: function(data) {
console.log(data);
},
error: function() {
console.log("error");
}
});
});
</script>
</html>
说明:
把 contentType 设置为 application/json,即 JSON 的 MIME 类型,发送的数据的类型是 JSON 字符串,后端使用 PHP 处理请求时,需要从 php://input 里获得原始输入流,再 json_decode 成对象;
serializeArray 会生成一个数组对象,每一个元素都表示一个表单 input 元素的属性的对象。
服务器端:
index2.php
<?php $data = file_get_contents('php://input'); // 从 php://input 里获得原始输入流
$data = json_decode($data, true); $response['code'] = 200;
$response['message'] = 'success';
$response['data'] = $data; header('content-type:text/json');
exit(json_encode($response));
POST 数据:
响应:
4. JSONP
同源策略:
浏览器有一种同源策略(Same origin policy),同源是指域名、协议、端口相同,当浏览器执行一个脚本(例如 JavaScript)的时候会检查这个脚本是否同源,否则不会执行该脚本,因为浏览器认为来自同站点的资源是安全的。在浏览器中,<script>、<img>、<iframe>、<link> 等标签都可以加载跨域资源,而不受同源限制,但浏览器限制了JavaScript 的权限使其不能读、写加载的内容。另外同源策略只对网页的 HTML 文档做了限制,对加载的其他静态资源如 JavaScript、css、图片等仍然认为属于同源。(参考:
例如,客户端通过 XMLHttpRequest 跨域与服务端交互,访问 http://www.site1.com/ajaxjson.html
ajaxjson.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script>
</head>
<body>
<script>
$.ajax({
url: "http://www.site2.com/index.php",
type: "post",
success: function(data) {
console.log(data);
},
error: function() {
console.log("error");
}
});
</script>
</body>
</html>
由于请求的域是 www.site2.com,属于跨域请求,所以在访问 http://www.site1.com/ajaxjson.html 时,浏览器会给出提示:
火狐下:
Chrome 下:
要解决这类跨域问题,可以使用 JSONP 作为解决方案。
JSONP:JSON with padding(参数式 JSON),包含在函数调用中的 JSON。如:
callback({"name": "dee"});
JSONP 利用在页面中创建 <script> 节点的方法向不同域提交 HTTP请求。例,两个域 http://www.site1.com 和 http://www.site2.com 实现跨域交互
客户端 site/index.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>site1</title>
</head>
<body>
<p id="response"></p>
</body>
<script>
function jsonCallback(data) {
document.getElementById("response").innerText = data.name;
console.log(data);
}
</script>
<script src="http://www.site2.com/index.php?callback=jsonCallback "></script>
</html>
服务端 site2/index.php:
<?php $callback = isset($_GET['callback']) ? $_GET['callback'] : ''; echo $callback.'({"name": "emperor"})';
访问 http://www.site1.com/index.html,返回:
说明:
其中 jsonCallback 是客户端注册的,获取跨域服务器上的 json 数据后,回调的函数。http://www.site2.com/index.php?callback=jsonpCallback 这个 url 是跨域服务器取 json 数据的接口,参数为回调函数的名字,返回的格式为:jsonpCallback({"name": "dee"}) 简述原理与过程:首先在客户端注册一个 callback, 然后把 callback 的名字传给服务器。此时,服务器先生成 json 数据。 然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数 jsonp 。最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。 客户端浏览器,解析 script 标签,并执行返回的 javascript 文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里。(动态执行回调函数)
(参考 JSONP跨域的原理解析)
同样的,jQuery 也对 JSONP 进行了封装,可以使用 jQuery 进行跨域请求:
site1/ajaxjsonp.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script>
</head>
<body>
<script>
$.ajax({
url: "http://www.site2.com",
dataType: "jsonp", // Tell jQuery we're expecting JSONP
jsonp: "callback", // 回调参数的名称 The name of the callback parameter
success: function(data) {
console.log(data);
},
error: function() {
console.log("error");
}
});
</script>
</body>
</html>
浏览器此时不会再提示已组织跨源请求而返回了服务端的数据:
JSONP 的优点是:它不像 XMLHttpRequest 对象实现的 Ajax 请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,不需要 XMLHttpRequest 或 ActiveX 的支持;并且在请求完毕后可以通过调用 callback 的方式回传结果。
JSONP 的缺点则是:它只支持 GET 请求而不支持 POST 等其它类型的 HTTP 请求。(参考 JSONP跨域的原理解析)
JSONP的最基本的原理是:动态添加一个 <script> 标签,而 script 标签的 src 属性是没有跨域的限制的。这样说来,这种跨域方式其实与 ajax XmlHttpRequest 协议无关了。更多原理可以参考 JSONP跨域的原理解析:
如果设为dataType: 'jsonp',这个$.ajax方法就和ajax XmlHttpRequest没什么关系了,取而代之的则是JSONP协议。JSONP是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问。 JSONP即JSON with Padding。由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源。如果要进行跨域请求, 我们可以通过使用html的script标记来进行跨域请求,并在响应中返回要执行的script代码,其中可以直接使用JSON传递javascript对象。 这种跨域的通讯方式称为JSONP。 jsonCallback 函数jsonp1236827957501(....):是浏览器客户端注册的,获取跨域服务器上的json数据后,回调的函数 Jsonp的执行过程如下: 首先在客户端注册一个callback (如:'jsoncallback'), 然后把callback的名字(如:jsonp1236827957501)传给服务器。注意:服务端得到callback的数值后,要用jsonp1236827957501(......)把将要输出的json内容包括起来,此时,服务器生成 json 数据才能被客户端正确接收。 然后以 javascript 语法的方式,生成一个function, function 名字就是传递上来的参数 'jsoncallback'的值 jsonp1236827957501 . 最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。 客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时javascript文档数据,作为参数, 传入到了客户端预先定义好的 callback 函数(如上例中jquery $.ajax()方法封装的的success: function (json))里。 可以说jsonp的方式原理上和<script src="http://跨域/...xx.js"></script>是一致的(qq空间就是大量采用这种方式来实现跨域数据交换的)。JSONP是一种脚本注入(Script Injection)行为,所以有一定的安全隐患。
5.其他跨域解决方案
CORS(跨域资源共享,Cross-Origin Resource Sharing)是 W3 的一项机制(https://www.w3.org/TR/cors/),跨源资源共享标准通过新增一系列 HTTP 头,让服务器能声明哪些来源可以通过浏览器访问该服务器上的资源。
例:
在 site2/cors.php 中添加 header:
header('Access-Control-Allow-Origin: *');
* 表示允许任何域向服务端提交请求
服务端代码:
<?php header('Access-Control-Allow-Origin: *'); $response['code'] = 200;
$response['message'] = 'success';
$response['name'] = 'dee'; header('Content-type: text/json');
exit(json_encode($response));
客户端 site1/cors.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script>
</head>
<body>
<script>
$.ajax({
url: "http://www.site2.com/cors.php",
type: "post",
dataType: "json",
success: function(data) {
console.log(data);
},
error: function() {
console.log("error");
}
});
</script>
</body>
</html>
浏览器 console 输出:
当把 header 改为:
header('Access-Control-Allow-Origin: http://www.site3.com');
即只允许来自 http://www.site3.com 的 AJAX 请求
再次访问 http://www.site1.com,由于设置了只允许 site3 的 AJAX 请求,所以浏览器输出:
把 header 再次改为:
header('Access-Control-Allow-Origin: http://www.site1.com');
输出:
参考:
《JavaScript高级程序设计》3nd
《精通jQuery》2nd
https://learn.jquery.com/ajax/working-with-jsonp/
JSON 与 JSONP的更多相关文章
- json和jsonp的区别,ajax和jsonp的区别
json和jsonp虽然只有一个字母的区别,但是它们之间扯不上关系. json是一种轻量级的数据交换格式. jsonp是一种跨域数据交互协议. json的优点:(1)基于纯文本传递极其简单,(2)轻量 ...
- [转]说说JSON和JSONP,也许你会豁然开朗,含jQuery用例
本文转自:http://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html 前言: 说到AJAX就会不可避免的面临两 ...
- JSON和JSONP (含jQuery实例)(share)
来源:http://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html 前言: 说到AJAX就会不可避免的面临两个问 ...
- 【转载】说说JSON和JSONP,也许你会豁然开朗,含jQuery用例
前言: 说到AJAX就会不可避免的面临两个问题,第一个是AJAX以何种格式来交换数据?第二个是跨域的需求如何解决?这两个问题目前都有不同的解决方案,比如数据可以用自定义字符串或者用XML来描述,跨域可 ...
- json和jsonp(json是目的,jsonp是手段)
自己理解:JSON是一种数据交换格式,而JSONP是一种依靠开发人员的聪明才智创造出的一种非官方跨域数据交互协议.我们拿最近比较火的谍战片来打个比方,JSON是地下党们用来书写和交换情报的" ...
- 用nodejs实现json和jsonp服务
一.JSON和JSONP JSONP的全称是JSON with Padding,由于同源策略的限制,XmlHttpRequest只允许请求当前源(协议,域名,端口)的资源.如果要进行跨域请求,我们可以 ...
- json 与jsonp 特点及区别
简单描述JSON跟JSONP的区别以及实战 什么是JSON? 前面简单说了一下,JSON是一种基于文本的数据交换方式,或者叫做数据描述格式,你是否该选用他首先肯定要关注它所拥有的优点. JSON的优点 ...
- 说说JSON和JSONP,也许你会豁然开朗,含jQuery用例 分类: JavaScript 2014-09-23 10:41 218人阅读 评论(1) 收藏
前言: 由于Sencha Touch 2这种开发模式的特性,基本决定了它原生的数据交互行为几乎只能通过AJAX来实现. 当然了,通过调用强大的PhoneGap插件然后打包,你可以实现100%的Sock ...
- php返回json,xml,JSONP等格式的数据
php返回json,xml,JSONP等格式的数据 返回json数据: header('Content-Type:application/json; charset=utf-8'); $arr = a ...
- json和jsonp的使用格式
最近一直在看关于json和jsonp的区别和各自的用法.优缺点! 下面是我看到过解释最清楚的一片文章 说到AJAX就会不可避免的面临两个问题,第一个是AJAX以何种格式来交换数据?第二个是跨域的需求 ...
随机推荐
- 听说awk语言也可以编写脚本
导读 从 awk 系列开始,我们都是在命令行或者脚本文件里写一些简短的 awk 命令和程序.然而 awk 和 shell 一样也是一个解释型语言.通过从开始到现在的一系列的学习,你现在能写可以执行的 ...
- coding.net就这么横空出世
各位新生们好: 看罢以上的开场白博客,我们也算初步完成了一个小程序——hello world.再进一步想下去,若我们程序写大了,要不停修改了(1000行代码不长,只争朝夕:-D),该如何保存呢?保存到 ...
- QuickSort 快速排序 基于伪代码实现
本文原创,转载请注明地址 http://www.cnblogs.com/baokang/p/4737492.html 伪代码 quicksort(A, lo, hi) if lo < hi p ...
- PHP中计划任务
PHP不支持多线程,有时候处理问题不是那么爽,今天谈论一下PHP定时执行的方法 PHP定时执行的三种方式实现 .windows 的计划任务 .linux的脚本程序 .让web浏览器定时刷新 windo ...
- yii2.0的分页和排序
//排序 $sort = new Sort([ 'attributes' => [ 'age' => [ 'asc' => ['age' => SORT_ASC], 'desc ...
- 《C#高级编程》之委托学习笔记 (转载)
全文摘自 http://www.cnblogs.com/xun126/archive/2010/12/30/1921551.html 写得不错,特意备份!并改正其中的错误代码.. 正文: 最近 ...
- 【Java EE 学习 47】【Hibernate学习第四天】【sesion】【一级缓存】【懒加载】
一.Session概述 1.Session 接口是 Hibernate 向应用程序提供的操纵对数据库的最主要的接口, 它提供了基本的保存, 更新, 删除和加载Java 对象的方法. 2.理解Sessi ...
- wp8 入门到精通 仿美拍评论黑白列表思路
static bool isbool = false; private void BindGameDelete() { Tile tile = new Tile(); List<Color> ...
- Windows 8.1安装 Vmware10
之前在windows 8上安装的Vmware 9.0,已经激活了用的蛮好,可是自从上次自动更新系统到windows 8.1后,启动虚拟机时提示要激活 使用各种激活码与注册机都无效,就算注册表信息丢失但 ...
- 【html+css】关于页面布局中遇到的问题记录
关于行内元素: 行内元素设置width无效, height无效(可以设置line-height), margin上下无效,padding上下无效,margin和padding可设置左右. text ...