JSON是一种数据格式,并不是一种编程语言。虽然与JavaScript具有相同的语法形式,但JSON并不从属于JavaScript。 JSON不支持变量,函数或对象实例,它就是一种表示结构化数据的格式
简单值: 字符串,数值,布尔和null。不支持JavaScript中的特殊值undefined对象:作为复杂数据类型,表示的是一组有序的键值对。每个键值对的值可以是简单类型也可以是复杂类型数组:表示一组有序的值的列表,可以通过数值索引来访问其中的值 JSON字符串必须使用双引号(单引号会导致语法错误)
JSON中对象与JavaScript字面量稍微有一些不同
JavaScript中的对象字面量:
var person = { name:"ethan", age:25 };
JSON对象:
{ "name":"ethan", "age":28 }
对象的属性必须加双引号
JavaScript数组:
var values = [25,"hi",true];
JSON数组:
[25,"hi",true]
早期使用eval()函数解析并返回JavaScript对象。 现在通过JSON全局对象来解析json
stringify():
将JavaScript对象序列化为JSON字符串
parse():
将JSON字符串解析为原生JavaScript值在序列化JavaScript对象时,所有函数及原型成员都会被忽略。此外,值为undefined的任何属性也会被跳过。结果中最终都是值为有效JSON数据类型的实例属性。
JSON.stringify()除了接收要序列化的JavaScript对象外,还可以接收另外两个参数。一:过滤器,可以是一个数组,也可以是一个函数;二:一个选项,表示 是否在JSON字符串中保留缩进。
1.过滤结果
如果过滤器参数是数组,那么JSON.stringify()的结果中将只包含数组中列出的属性
var person = { name:"zhangsan", "age":34, "hobbit":["football","basketball",'volleyball'], son:{ name:"李四", age:10 } }; var json = JSON.stringify(person,["name","age"]); console.log(json);// {"name":"zhangsan","age":34}
如果过滤参数是函数
var json = JSON.stringify(person,function(key,value){ switch(key){ case "name": return value; case "age": return undefined;//跳过指定的属性 case "hobbit": return value.join(","); default: return value; } }); console.log(json);// {"name":"zhangsan","hobbit":"football,basketball,volleyball","son":{"name":"李四"}}
JSON.stringify()方法的第三个参数控制结果中的缩进和空白符。
var person = { name:"zhangsan", "age":29, hobbit:["basketball","sing","eat"], son:{ name:"lisi", age:4 } }; var json = JSON.stringify(person,null,2); console.log(json);
输出格式如下:
{ "name": "zhangsan", "age": 29, "hobbit": [ "basketball", "sing", "eat" ], "son": { "name": "lisi", "age": 4 } }最大缩进空格数为10,超过10就取10
缩进字符串参数: 自负串替代空格
var json = JSON.stringify(person,null,"- -"); console.log(json);{ - -"name": "zhangsan", - -"age": 29, - -"hobbit": [ - -- -"basketball", - -- -"sing", - -- -"eat" - -], - -"son": { - -- -"name": "lisi", - -- -"age": 4 - -} }
3.toJSON()方法
有时候JSON.stringify()并不能满足对某些对象进行自定义序列化的需求。这种情况下,可以通过对象上调用toJSON()方法,返回自身的JSON数据格式。原生Date对象有一个toJSON()方法,将JavaScript的Date对象自动转换成ISO 8601日期字符串(与Date上调用toISOString()结果一样)。
var person = { name:"zhangsan", "age":34, "hobbit":["football","basketball",'volleyball'], son:{ name:"李四", age:10 }, toJSON:function(){ //自定义json转换方法 return this.name; } }; var jsonText = JSON.stringify(person); console.log(jsonText); //zhangsan
toJSON()可以作为函数过滤器的补充,对象序列化顺序如下:
如果存在toJSON()方法且能通过它取得有效的值,则调用该方法。否则,按默认顺序执行序列化如果提供了第二个参数,应用这个函数过滤器。传入函数过滤器的值是第(1)步返回的值对第(2)步返回的值进行序列化如果提供了第三个参数,执行相应的格式化
JSON.parse()方法可以接受一个参数,该参数是一个函数,在每个键值对上调用。称为(reviver)还原函数
如果函数返回undefined,表示从结果中删除相应的键;如果返回其他值,表示将该值插入到结果中。
var person = { name:"zhangsan", "age":34, "hobbit":["football","basketball",'volleyball'], son:{ name:"李四", age:10 }, birthday:new Date(2016,6,8) }; var jsonText = JSON.stringify(person); console.log(jsonText); var personCopy = JSON.parse(jsonText,function(key,value){ if(key == 'birthday'){ //否则返回日期字符串 return new Date(value); }else{ return value; } }); console.log(personCopy);
open():接收三个参数,请求方式(get,post等),请求URL,是否异步发送请求
并不会真正发送请求,只是启动一个请求以备发送。只能向同一个域中使用相同端口和协议的URL发送请求。
send():发送请求,一个参数(要发送的请求数据)。在收到响应后,响应的数据会自动填充XHR对象的属性 responseText:作为响应主体被返回的文本,无论内容类型是什么。responseXML:如果响应内容是"text/xml"或"application/xml",这个属性中将保存包含着响应数据的XML DOM文档。status:响应的HTTP状态statusText:HTTP状态说明
var xhr = new XMLHttpRequest();
// console.log(xhr);
xhr.open("post","....url...",false);
xhr.send(null);
if((xhr.status >=200 && xhr.status<300)||xhr.status ==304){
// console.log(xhr.responseText);
console.log(xhr.status);
}else{
console.log("request fail");
}
发送异步请求(JS继续执行不必等待响应)。通过检测XHR的readyState属性来判断响应状态 0:未初始化,尚未调用open()方法1:启动。已经调用open()方法2:发送。已经调用send()方法3:接收。已经接收到部分响应数据4:完成。已经接收到全部响应数据,可以在客户端使用 readyState属性值变化都会触发readystatechange事件。必须在open()方法调用前指定onreadystatechange事件处理程序才能保证跨浏览器兼容性。
var xhr = new XMLHttpRequest(); //检测状态变化 xhr.onreadystatechange = function(){ console.log(xhr.readyState); if(xhr.readyState == 4){//响应完成 if((xhr.status >=200 && xhr.status<300)||xhr.status ==304){ // console.log(xhr.responseText); console.log(xhr.status); }else{ console.log("request fail"); } } } // console.log(xhr); xhr.open("post",".....",false); xhr.send(null);
在接收响应之前可以调用abort()方法来取消异步请求 xhr.abort();
XHR提供setRequestHeader(key,value)来操作http请求消息头
Accept:浏览器能处理的内容类型Accept-Charset:浏览器能显示的字符集Accept-Encoding:浏览器能处理的压缩编码Accept-Language:浏览器当前设置的语言Connection:浏览器与服务器之间连接的类型Cookie:当前页面设置的任何CookieHost:发出请求的页面所在的域Referer:发出请求的页面URL(防止盗链)User-Agent:浏览器的用户代理字符串 必须在open()之后,send()之前调用setRequestHeader() getResponseHeader();获取响应头对应的信息 getAllResponseHeader():获取包含所有头部信息的长字符串
var xhr = new XMLHttpRequest(); //检测状态变化 xhr.onreadystatechange = function(){ console.log(xhr.readyState); if(xhr.readyState == 4){//响应完成 if((xhr.status >=200 && xhr.status<300)||xhr.status ==304){ var allHeaders = xhr.getAllResponseHeaders(); console.log(allHeaders); }else{ console.log("request fail"); } } } xhr.open("post","wgps/tmsweb/showDomesticRoute.action?referenceCode=HTM201607170132201",false); xhr.setRequestHeader("MyHead","hehe"); xhr.send(null);
查询字符串参数追加到URL末尾发送给服务器。对XHR而言,位于传入open()的URL末尾的查询字符串必须经过正确的编码才行 每个参数的名称和值都必须使用encodeURIComponent()进行编码
function addURLParam(url,name,value){ url += (url.indexOf("?")== -1 ? '?':'&'); url += encodeURIComponent(name)+"="+encodeURIComponent(value); return url; }
send():向服务器发送数据,作为请求的主体提交。
由于XHR最初的设计主要是为了处理XML,因此可以传入XML DOM文档,传入的文档经序列化之后将作为请求主体被提交到服务器。当然,也可以在此传入任何想发送到服务器的字符串
默认情况下,服务器对POST请求和提交Web表单的请求不会一视同仁。因此服务器端必须有程序来读取发送过来的原始数据,并从中解析出有用的部分。
可以使用XHR模仿表单提交。将Content-Type头部信息设置为application/x-www-form-urlencoded(表单提交时的内容类型),然后提交表单序列化后的格式参数。
xhr.open("post","....",true);
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(serialize(form));
与GET请求相比,POST请求消耗的资源会更多。从性能角度看,发送相同的数据,GET请求的速度最多可达到POST请求的两倍。
FormData为序列化表单以及创建与表单格式相同的数据(用于通过XHR传输)提供了便利。
键值对
var data = new FormData(); data.append("name","zhangsan");
直接构造函数传入表单
var data = new FormData(document.forms[0]);
不必设置请求头。XHR对象能识别传入的数据类型是FormData的实例
xhr.send(new FormData(document.forms[0]));
XHR对象timeout属性,请求在等待响应指定毫秒后就终止。如果在规定时间内没有接收到响应,就会触发timeout事件,进而调用ontimeout事件处理程序。
var xhr = new XMLHttpRequest();
//检测状态变化
xhr.onreadystatechange = function(){
console.log(xhr.readyState);
if(xhr.readyState == 4){//响应完成
try{
if((xhr.status >=200 && xhr.status<300)||xhr.status ==304){
var allHeaders = xhr.getAllResponseHeaders();
console.log(allHeaders);
}else{
console.log("request fail");
}
}catch(err){
console.log(err);
}
}
}
xhr.open("post","...",true);
xhr.timeout = 1000;//将超时设置为1秒
xhr.ontimeout = function(){
console.log("请求超时");
}
xhr.send(null);
如果1秒钟内没有返回就会自动终止。readyState变为4,触发onreadystatechange事件处理程序。超时后再访问status属性,会导致报错。
所以将status检测的代码放到try-catch语句中
用来重写XHR响应的MIME类型。必须在send()方法前
xhr.overrideMimeType("text/xml"); xhr.send(null);
loadstart:接收到响应数据的第一个字节时触发progress:接收响应期间持续不断地触发error:请求发生错误时触发abort:在调用abort()方法终止连接时触发load:在接收到完整响应数据时触发loadend:在通信完成或触发error,abort或load时间后触发 从触发loadstart事件开始,接下来是一个或多个progress事件,然后触发error,abort或load事件中的一个,最后触发loadend事件结束
用来替代readystatechange事件,响应接收完毕后触发load事件,不用检查readyState属性。
而onload事件处理程序会接收到一个event对象,target属性就指向XHR对象实例
var xhr = new XMLHttpRequest(); xhr.onload = function(event){ console.log(event.target);//XHR对象 if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ console.log("success"+xhr.status); }else{ console.log("fail"+xhr.status); } } xhr.open("get","...",true); xhr.send(null);
只要浏览器接收到服务器响应。不管状态如何,都会触发load事件
在浏览器接收新数据期间周期性地触发。onprogress事件处理程序会接收到一个event对象,target属性是XHR对象,包含三个额外属性:
lengthComputable:进度信息是否可用
position:已经接收的字节数
totalSize:根据Content-Length响应头消息确定的预期字节数
可以给用户创建一个进度指示器
xhr.onprogress = function(event){ var divStatus = document.getElementById("editDiv"); if(event.lengthComputable){ divStatus.innerHTML = "received"+event.position+" of " +event.totalSize +"bytes"; } }
必须在调用open()方法之前添加onprogress事件处理程序
CORS(Cross-Origin Resource Sharing,跨源资源共享),定义了在必须访问跨源资源时,浏览器与服务器应该如何沟通。使用自定义HTTP头部让浏览器与服务器沟通。 比如一个简单的使用GET或POST发送的请求,没有自定义头部,主体内容是text/plain。在发送请求时,需要给它附加一个额外的Origin头部,其中包含请求页面的资源信息(协议,域名,和端口),一般服务器根据这个头部信息来决定是否给予响应。 Origin:http://www.baidu.com
如果服务器认为这个请求可以接受,就在Access-Control-Allow-Origin头部中回发相同的源信息(如果是公共资源,可以回发"*"). Access-Control-Allow-Origin:http://www.baidu.com
如果没有这个头部,或这个头部信息不匹配,浏览器会驳回请求。正常情况下,浏览器会处理请求,但请求和响应不包含cookie信息。
当使用XMLHttpRequest发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头:Origin,后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin;浏览器判断该相应头中是否包含Origin的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据
XDR(XDomainRequest)。该对象与XHR类似。部分实现了CORS规范 cookie不会随请求发送,也不会随响应返回只能设置请求头中的Content-Type字段不能访问响应头部信息只支持GET和POST请求 所有XDR请求都是异步执行,请求返回后会触发load事件,响应数据保存在responseText属性。
Firefox3.5+,Safari4+,Chrome通过XMLHttpRequest对象实现了对CORS的原生支持,跨域访问不需要额外代码,在open()中传入绝对URL即可。
apache服务器 :http://localhost/ 上的html
var xhr = new XMLHttpRequest(); // console.log(xhr); xhr.onload = function(event){ console.log(event.target);//XHR对象 if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){ console.log(xhr.responseText); }else{ console.log("fail"+xhr.status); } } xhr.open("post","http://localhost:8080/wgps/servlet/CROSServlet",false);//访问tomcat上的servlet xhr.send(null);
报错: XMLHttpRequest cannot load http://localhost:8080/wgps/servlet/CROSServlet. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. 在tomcat服务器端,设置响应消息头的属性
response.setHeader("Access-Control-Allow-Origin", "http://localhost");就可以正常实现跨域访问
XHR对象可以访问status和statusText属性,并且支持同步请求。同时也有如下限制:
不能使用setRequestHeader()设置自定义头部不能发送和接收cookie调用getAllResponseHeaders()方法总会返回空字符串 在访问本地资源时,最好使用相对URL,避免出现限制访问头部或本地cookie信息等问题。
CORS通过Preflighted Requests的透明服务器验证机制支持开发人员使用自定义的头部,GET或POST之外的方法,以及不同类型的主体内容。 向服务器发送一个Preflight请求,这种请求使用OPTIONS方法。 Origin:与简单请求相同。Access-Control-Request-Method:请求自身使用的方法Access-Control-Request-Headers:(可选)自定义的头部信息,多个信息以逗号分隔。
在CORS出现以前,要实现跨域Ajax通信颇费一些周折。利用DOM中能够执行跨域请求的功能,在不依赖XHR对象的情况下也能发送某种请求。
使用标签。一个网页可以从任何网页中加载图像,不用担心跨域问题。这也是在线广告跟踪浏览量的主要方式。可以动态地创建图像,使用它们的onload和onerror事件处理程序来确定是否接收到了响应。
动态创建图像经常用于图像Ping。图像Ping是与服务器进行简单,单向的跨域通信的一种方式。
请求的数据通过查询字符串形式发送,响应可以是任意内容,通常是像素图或204响应。
通过图像Ping,浏览器得不到任何具体的数据,但通过侦听load和error事件,能知道响应是什么时候接收到的
var img = new Image(); img.onload = function(){ console.log("done!"); } img.onerror = function(){ console.log("error!"); } img.src = "http://www.baidu.com";
JSONP是JSON with padding(填充式JSON或参数式JSON)的简写,是应用JSON的一种新方法。JSONP看起来与JSON差不多,只不过是被包含在函数调用中的JSON,如:
callback({"name":"zhangsan"});
由两部分组成:1.回调函数,当响应到来时应该在页面中调用的函数,一般在请求中指定回调函数的名字。
2.数据,传入回调函数中的JSON数据。
function handleResponse(response){ console.log(response); } var script = document.createElement("script"); script.src = "http://localhost:8080/wgps/tmsweb/queryFreightOrderByPage.action?callback=handleResponse"; document.body.insertBefore(script,document.body.firstChild);