1.json与jsonp的引入
在ajax中 JSON用来解决数据交换问题,而JSONP来实现跨域。
备注:跨域也可以通过服务器端代理来解决;
理解:JSON是一种数据交换格式,而JSONP是一种依靠开发人员的聪明才智创造出的一种非官方跨域数据交互协议。
2.JSON:是一种基于文本的数据交换方式,或者叫做数据描述格式,是否该选用它首先肯定要关注它所拥有的优点。
JSON的优点:
JSON的格式或者叫规则:
JSON能够以非常简单的方式来描述数据结构,XML能做的它都能做,因此在跨平台方面两者完全不分伯仲。
只是建议如果客户端没有按日期排序功能需求的话,那么把日期时间直接作为字符串传递就好,可以省去很多麻烦。
示列1:{} 用来描述一组“不同类型的无序键值对集合”
var person = {
"Name": "Bob",
"Age": 32,
"Company": "IBM",
"Engineer": true
}
示列2:[] 用来描述一组“相同类型的有序数据集合”
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;
示列3:{}中包含的[]使用
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;
3.什么是JSONP
JSONP(JSON with Padding)是资料格式 JSON 的一种“使用模式”,可以让网页从别的网域要资料。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的 <script> 元素是一个例外。利用<script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的资料并不是 JSON,而是任意的 JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。
3.1 JSOPN跨域的原理:script标签的src属性,支持跨域;它的基本思想是,网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
3.2 JSOP包含两部分:回调函数和数据,回调函数是在响应到来时应该调用的函数,一般通过查询字符串添加; 数据就是传入回调函数中的JSON数据,确切的说,是一个JSON对象,可以直接访问。
3.3 JSONP的缺点:
1) 只能实现GET,没有POST;
2) 从其他域中加载的代码可能不安全;难以确定JSONP请求是否失败(XHR有error事件),常见做法是使用定时器指定响应的允许时间,超出时间认为响应失败。
为了方便客户端使用数据逐渐形成非正式传输协议jsonp该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住json数据 这样客户端就可以随意定制自己的函数来自动处理返回数据
示列:
function ajaxFun(){
var strUrl="http://www.b.com/demo/json.txt";
$.ajax({
type:"get",
url:strUrl,
dataType: 'jsonp',
jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback: "flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
success: function(data){
alert('您查到的信息:票价' + data.price + '元,余-票' + data.tickets + '张。');
},
error: function(XMLHttpRequest,textStatus,errorThrown){
alert("error");
// 状态码
console.log(XMLHttpRequest.status);
// 状态
console.log(XMLHttpRequest.readyState);
// 错误信息
console.log(textStatus);
}
});
}
备注:
其中 sucess中的代码片段也可以不写,可以单独建立一个回调函数来调用返回的数据。如下一样可以获得数据。
var flightHandler = function (data) {
alert('您查到的信息:票价' + data.price + '元,余票' + data.tickets + '张。');
};
需要注意的是,ajax跨域请求(jsonp)中,服务端返回数据格式必须是:flightHandler({ "price":"120","tickets":"20"});如果直接这样的json格式{ "price":"120","tickets":"20"},将会报parser error的错误.请注意这个函数最后的分号";",必须加上,否则,如果同一个页面有多个ajax请求, 并且在数据没有返回时,再发出其它ajax请求时,有可能出现parsererror出错提示.这种错误很隐敝,在开发时,不容易发现,在并发测试时,就很容易暴露出.
服务端代码示列:
public String jsonReturn(HttpServletResponse response, String callback, Map<String, Object> jsonMap) {
if (org.apache.commons.lang.StringUtils.isEmpty(callback)) {
return appAjaxJson(response, getJson(jsonMap));
}
return appAjaxJson(response, callback + "(" + getJson(jsonMap) + ")");
}
public String appAjaxJson(HttpServletResponse response, String jsonString) {
return appAjax(response, jsonString, "text/html");
}
public String appAjax(HttpServletResponse response, String content, String type) {
try {
response.setContentType(type + ";charset=UTF-8");
response.setHeader("Access-Control-Allow-Origin", "*");//表示支持跨域请求
// 如果IE浏览器则设置头信息如下
if ("IE".equals(type)) {
response.addHeader("XDomainRequestAllowed", "1");
}
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.getWriter().write(content);
response.getWriter().flush();
} catch (IOException e) {
this.logException(e);
}
return null;
}
4、JSON.stringify()、JSON.parse()、toString()
4.1 JSON.stringify():将入参(JavaScript值)转换为 JSON 字符串;
示列1:
let arr = [1,2,3];
JSON.stringify(arr);//"[1,2,3]"
typeof JSON.stringify(arr);//"string"
示例2:
//判断数组是否包含某对象
let data = [
{name:'echo'},
{name:'听风是风'},
{name:'天子笑'},
],
val = {name:'天子笑'};
JSON.stringify(data).indexOf(JSON.stringify(val)) !== -1;//true
//判断两数组/对象是否相等
let a = [1,2,3],
b = [1,2,3];
JSON.stringify(a) === JSON.stringify(b);//true
4.2 JSON.parse():将JSON字符串转为一个对象;
示列:
let string = '[1,2,3]';
console.log(JSON.parse(string))//[1,2,3]
console.log(typeof JSON.parse(string))//object
4.3 JSON.stringify()与 toString()的区别
let arr = [1,2,3];
JSON.stringify(arr);//'[1,2,3]'
arr.toString();//1,2,3