1. 程式人生 > >$.ajax()方法從伺服器獲取json資料幾種方式詳解

$.ajax()方法從伺服器獲取json資料幾種方式詳解

一.什麼是json

json是一種取代xml的資料結構,和xml相比,它更小巧但描述能力卻很強,網路傳輸資料使用流量更少,速度更快。

json就是一串字串,使用下面的符號標註。

{鍵值對} : json物件

[{},{},{}] :json陣列

"" :雙引號內是屬性或值

: :冒號前為鍵,後為值(這個值可以是基本資料型別的值,也可以是陣列或物件),所以 {"age": 18} 可以理解為是一個包含age為18的json物件,而[{"age": 18},{"age": 20}]就表示包含兩個物件的json陣列。也可以使用{"age":[18,20]}來簡化上面的json陣列,這是一個擁有一個age陣列的物件。

二.$.ajax()方法中dataType屬性的取值

$.ajax()方法中dataType屬性要求為String型別的引數,預期伺服器返回的資料型別。如果不指定,JQuery將自動根據http包mime資訊返回responseXML或responseText【在第三部分解釋】,並作為回撥函式引數傳遞。可用的型別如下:

xml:返回XML文件,可用JQuery處理。

html:返回純文字HTML資訊;包含的script標籤會在插入DOM時執行。

script:返回純文字JavaScript程式碼。不會自動快取結果。除非設定了cache引數。注意在遠端請求時(不在同一個域下),所有post請求都將轉為get請求。

json:返回JSON資料。

jsonp:JSONP格式。使用SONP形式呼叫函式時,例如myurl?callback=?,JQuery將自動替換後一個“?”為正確的函式名,以執行回撥函式。

三.Mime資料型別及response的setContentType()方法

什麼是MIME型別?在把輸出結果傳送到瀏覽器上的時候,瀏覽器必須啟動適當的應用程式來處理這個輸出文件。這可以通過多種型別MIME(多功能網際郵件擴充協議)來完成。在HTTP中,MIME型別被定義在Content-Type header中。

如,架設你要傳送一個Microsoft Excel檔案到客戶端。那麼這時的MIME型別就是“application/vnd.ms-excel”。在大多數實際情況中,這個檔案然後將傳送給 Execl來處理(假設我們設定Execl為處理特殊MIME型別的應用程式)。在Java中,設定MIME型別的方法是通過Response物件的ContentType屬性。比如常用:response.setContentType("text/html;charset=UTF-8")進行設定。

最早的HTTP協議中,並沒有附加的資料型別資訊,所有傳送的資料都被客戶程式解釋為超文字標記語言HTML 文件,而為了支援多媒體資料型別,HTTP協議中就使用了附加在文件之前的MIME資料型別資訊來標識資料型別。

每個MIME型別由兩部分組成,前面是資料的大類別,例如文字text、圖象image等,後面定義具體的種類。

常見的MIME型別:

超文字標記語言文字 .html,.html text/html

普通文字 .txt text/plain

RTF文字 .rtf application/rtf

GIF圖形 .gif image/gif

JPEG圖形 .ipeg,.jpg image/jpeg

au聲音檔案 .au audio/basic

MIDI音樂檔案 mid,.midi audio/midi,audio/x-midi

RealAudio音樂檔案 .ra, .ram audio/x-pn-realaudio

MPEG檔案 .mpg,.mpeg video/mpeg

AVI檔案 .avi video/x-msvideo

GZIP檔案 .gz application/x-gzip

TAR檔案 .tar application/x-tar

客戶程式從伺服器上接收資料的時候,它只是從伺服器接受資料流,並不瞭解文件的名字,因此伺服器必須使用附加資訊來告訴客戶程式資料的MIME型別。

伺服器在傳送真正的資料之前,就要先發送標誌資料的MIME型別的資訊,這個資訊使用Content-type關鍵字進行定義,例如對於HTML文件,伺服器將首先發送以下兩行MIME標識資訊,這個標識並不是真正的資料檔案的一部分。

Content-type: text/html

注意,第二行為一個空行,這是必須的,使用這個空行的目的是將MIME資訊與真正的資料內容分隔開。

如前面所說,在Java中,設定MIME型別的方法是通過Response物件的ContentType屬性,設定的方法是使用response.setContentType(MIME)語句,response.setContentType(MIME)的作用是使客戶端瀏覽器,區分不同種類的資料,並根據不同的MIME呼叫瀏覽器內不同的程式嵌入模組來處理相應的資料。

Tomcat的安裝目錄\conf\web.xml中就定義了大量MIME型別 ,可以參考。比如可以設定:

response.setContentType("text/html; charset=utf-8"); html

response.setContentType("text/plain; charset=utf-8"); 文字

application/json json資料

這個方法設定傳送到客戶端的響應的內容型別,此時響應還沒有提交。給出的內容型別可以包括字元編碼說明,例如:text/html;charset=UTF-8。如果該方法在getWriter()方法被呼叫之前呼叫,那麼響應的字元編碼將僅從給出的內容型別中設定。該方法如果在getWriter()方法被呼叫之後或者在被提交之後呼叫,將不會設定響應的字元編碼,在使用http協議的情況中,該方法設定 Content-type實體報頭。

四.使用$.ajax()方法獲取json資料的三種方式

dataType引數的配置決定了jquery如何幫助我們自動解析伺服器返回的資料,有幾種方式可以獲取後臺返回的json字串並解析為json物件,下面是Java為例解釋,下面三中方式的結果都是圖一所示,專案執行在內網,無法截圖,只能拍照,見諒。


1、$.ajax()引數中不設定dataType,後臺response也不設定返回型別,則預設會以普通文字處理【response.setContentType("text/html;charset=utf-8");也是作為文字處理】,js中需要手動使用eval()或$.parseJSON()等方法將返回的字串轉換為json物件使用。

//Java程式碼:後臺獲取單個數控定位器的歷史表格的資料
	public void getHistorySingleData() throws IOException{
		HttpServletRequest request = ServletActionContext.getRequest();
		HttpServletResponse response = ServletActionContext.getResponse();
		response.setHeader("Content-type", "text/html;charset=UTF-8");
		response.setContentType("text/html;charset=utf-8");
		String deviceName = request.getParameter("deviceName");
		String startDate= request.getParameter("startDate");
		String endDate = request.getParameter("endDate");
		SingleHistoryData[] singleHistoryData = chartService.getHistorySingleData(deviceName,startDate, endDate);
		System.out.println(singleHistoryData.length);
		System.out.println(JSONArray.fromObject(singleHistoryData).toString());//列印:[{"time":"2016-11-11 10:00:00","state":"執行","ball":"鎖緊",....},{"time":"2016-11-11 10:00:05","state":"執行","ball":"鎖緊",....},{},{}....]查到幾條singleHistoryData物件就列印幾個物件的資訊{"time":"2016-11-11 10:00:05","state":"執行","ball":"鎖緊",....}
		response.getWriter().print(JSONArray.fromObject(singleHistoryData).toString());
	}

	/*js程式碼:選擇查詢某一時間段的資料,點選查詢之後進行顯示*/
    $("#search").click(function () {
    	var data1 = [];
    	var n;
    	var deviceName=$("body").attr("id"); 
        var startDate = $("#startDate").val();
        var endDate = $("#endDate").val();
        $.ajax({
           url:"/avvii/chart/getHistorySingleData",
           type:"post",
           data:{
               "deviceName":deviceName,
               "startDate": startDate,
               "endDate": endDate
           },
           success: function (data) {
        	   alert(data);//---->彈出[{"time":"2016-11-11 10:00:00","state":"執行","ball":"鎖緊",....},{"time":"2016-11-11 10:00:05","state":"執行","ball":"鎖緊",....},{},{}....],後臺傳過來幾條singleHistoryData物件就列印幾個物件的資訊{"time":"2016-11-11 10:00:05","state":"執行","ball":"鎖緊",....}
    		   alert(Object.prototype.toString.call(data));  //--->彈出[object String],說明獲取的是String型別的資料
        	   var JsonObjs = eval("(" + data + ")");      //或者:var JsonObjs = $.parseJSON(data);
    		   alert(JsonObjs);//alert(JsonObjs);---->彈出[object Object],[object Object],[object Object][object Object],[object Object],[object Object]……後臺傳過來幾條singleHistoryData物件就列印幾個[object Object]
               n=JsonObjs.length;
               if(n==0){
            	   alert("您選擇的時間段無資料,請重新查詢");
               }
    		   for(var i = 0; i < JsonObjs.length; i++){	                      
		       	        var name  = JsonObjs[i]['time'];//針對每一條資料:JsonObjs[i],或者:JsonObjs[i].time
		    	        var state = JsonObjs[i]['state'];
		    	        var ball  = JsonObjs[i]['ball'];
		    	        var xd    = JsonObjs[i]['xd'];
		    	        var yd    = JsonObjs[i]['yd'];
		    	        var zd    = JsonObjs[i]['zd'];
		    	        var xf    = JsonObjs[i]['xf'];
		    	        var yf    = JsonObjs[i]['yf'];
		    	        var zf    = JsonObjs[i]['zf'];
                        data1[i] = {name:name,state:state,ball:ball,xd:xd,yd:yd,zd:zd,xf:xf,yf:yf,zf:zf};//個數與下面表頭對應起來就可以了,至於叫什麼名字並不影響控制元件的使用
               }
    		   if(JsonObjs.length != 10){
    			   for(var j=0;j<(10-((JsonObjs.length)%10));j++){               //補全最後一頁的空白行,使表格的長度保持不變
    				   data1[j+JsonObjs.length] = {name:" ",state:"",ball:"",xd:"",yd:"",zd:"",xf:"",yf:"",zf:""}; 
    			   }
    		   }
               var userOptions = {
                       "id":"kingTable",                                				//必須 表格id
                       "head":["時間","執行狀態","球頭狀態","X向位置/mm","Y向位置/mm","Z向位置/mm","X向承載力/Kg","Y向承載力/Kg","Z向承載力/Kg"],  //必須 thead表頭
                       "body":data1,                                    				//必須 tbody 後臺返回的資料展示
                       "foot":true,                                    					// true/false  是否顯示tfoot --- 預設false
                       "displayNum": 10,                               					//必須   預設 10  每頁顯示行數
                       "groupDataNum":6,                             					//可選    預設 10  組數
                       sort:false,                                    					// 點選表頭是否排序 true/false  --- 預設false
                       search:false,                                  					// 預設為false 沒有搜尋
                       lang:{
                           gopageButtonSearchText:"搜尋"
                       }
               }
               var cs = new KingTable(null,userOptions);
           }
       }); 
   });

2、$.ajax()引數中設定dataType="json",則jquery會自動將返回的字串轉化為json物件。後臺可以設定為:推薦response.setContentType("text/html;charset=utf-8");或者response.setContentType("application/json;charset=utf-8");

	//Java程式碼:後臺獲取單個數控定位器的歷史表格的資料
	public void getHistorySingleData() throws IOException{
		HttpServletRequest request = ServletActionContext.getRequest();
		HttpServletResponse response = ServletActionContext.getResponse();
		response.setHeader("Content-type", "text/html;charset=UTF-8");
		response.setContentType("text/html;charset=utf-8");
		String deviceName = request.getParameter("deviceName");
		String startDate= request.getParameter("startDate");
		String endDate = request.getParameter("endDate");
		SingleHistoryData[] singleHistoryData = chartService.getHistorySingleData(deviceName,startDate, endDate);
		System.out.println(singleHistoryData.length);
		System.out.println(JSONArray.fromObject(singleHistoryData).toString());//列印:[{"time":"2016-11-11 10:00:00","state":"執行","ball":"鎖緊",....},{"time":"2016-11-11 10:00:05","state":"執行","ball":"鎖緊",....},{},{}....]查到幾條singleHistoryData物件就列印幾個物件的資訊{"time":"2016-11-11 10:00:05","state":"執行","ball":"鎖緊",....}
		response.getWriter().print(JSONArray.fromObject(singleHistoryData).toString());
	}
/*js程式碼:頁面首次載入時,顯示規定時間段的資料*/ 
	var data1 = [];
	var deviceName=$("body").attr("id"); 
    var startDate = $("#startDate").val("2000-01-01 00:00:00");
    var endDate = $("#endDate").val("2018-01-01 00:00:00");
    $.ajax({
       url:"/avvii/chart/getHistorySingleData",
       type:"post",
       data:{
           "deviceName":deviceName,
           "startDate": "2000-01-01 00:00:00",
           "endDate": "2018-01-01 00:00:00"
       },
       dataType:"json",
       success: function (data) {
    	   alert(data);//---->彈出[object Object],[object Object],[object Object][object Object],[object Object],[object Object]……後臺傳過來幾條singleHistoryData物件就列印幾個json物件:[object Object]
           for(var i = 0; i < data.length; i++){	                      
	       	        var name  = data[i]['time'];
	    	        var state = data[i]['state'];
	    	        var ball  = data[i]['ball'];
	    	        var xd    = data[i]['xd'];
	    	        var yd    = data[i]['yd'];
	    	        var zd    = data[i]['zd'];
	    	        var xf    = data[i]['xf'];
	    	        var yf    = data[i]['yf'];
	    	        var zf    = data[i]['zf'];
                    data1[i] = {name:name,state:state,ball:ball,xd:xd,yd:yd,zd:zd,xf:xf,yf:yf,zf:zf};
           }
		   if(data.length != 10){
			   for(var j=0;j<(10-((data.length)%10));j++){               //補全最後一頁的空白行,使表格的長度保持不變
				   data1[j+data.length] = {name:" ",state:"",ball:"",xd:"",yd:"",zd:"",xf:"",yf:"",zf:""}; 
			   }
		   }
           var userOptions = {
                   "id":"kingTable",                                				//必須 表格id
                   "head":["時間","執行狀態","球頭狀態","X向位置/mm","Y向位置/mm","Z向位置/mm","X向承載力/Kg","Y向承載力/Kg","Z向承載力/Kg"],  //必須 thead表頭
                   "body":data1,                                    				//必須 tbody 後臺返回的資料展示
                   "foot":true,                                    					// true/false  是否顯示tfoot --- 預設false
                   "displayNum": 10,                               					//必須   預設 10  每頁顯示行數
                   "groupDataNum":6,                             					//可選    預設 10  組數
                   sort:false,                                    					// 點選表頭是否排序 true/false  --- 預設false
                   search:false,                                  					// 預設為false 沒有搜尋
                   lang:{
                       gopageButtonSearchText:"搜尋"
                   }
           }
           var cs = new KingTable(null,userOptions);
       }
   }); 

3、ajax方法引數中不指定dataType,後臺設定返回型別為"application/json"。這樣jquery就會根據mime型別來智慧判斷,並自動解析成json物件

	//Java程式碼:後臺獲取單個數控定位器的歷史表格的資料
	public void getHistorySingleData() throws IOException{
		HttpServletRequest request = ServletActionContext.getRequest();
		HttpServletResponse response = ServletActionContext.getResponse();
		response.setHeader("Content-type", "text/html;charset=UTF-8");
		response.setContentType("application/json;charset=utf-8");
		String deviceName = request.getParameter("deviceName");
		String startDate= request.getParameter("startDate");
		String endDate = request.getParameter("endDate");
		SingleHistoryData[] singleHistoryData = chartService.getHistorySingleData(deviceName,startDate, endDate);
		System.out.println(singleHistoryData.length);
		System.out.println(JSONArray.fromObject(singleHistoryData).toString());//列印:[{"time":"2016-11-11 10:00:00","state":"執行","ball":"鎖緊",....},{"time":"2016-11-11 10:00:05","state":"執行","ball":"鎖緊",....},{},{}....]查到幾條singleHistoryData物件就列印幾個物件的資訊{"time":"2016-11-11 10:00:05","state":"執行","ball":"鎖緊",....}
		response.getWriter().print(JSONArray.fromObject(singleHistoryData).toString());
	}

   /*js程式碼:頁面首次載入時,顯示規定時間段的資料*/ 
	var data1 = [];
	var deviceName=$("body").attr("id"); 
    var startDate = $("#startDate").val("2000-01-01 00:00:00");
    var endDate = $("#endDate").val("2018-01-01 00:00:00");
    $.ajax({
       url:"/avvii/chart/getHistorySingleData",
       type:"post",
       data:{
           "deviceName":deviceName,
           "startDate": "2000-01-01 00:00:00",
           "endDate": "2018-01-01 00:00:00"
       },
       success: function (data) {
    	   alert(data);//---->彈出[object Object],[object Object],[object Object][object Object],[object Object],[object Object]……後臺傳過來幾條singleHistoryData物件就列印幾個json物件:[object Object]
           for(var i = 0; i < data.length; i++){	                      
	       	        var name  = data[i]['time'];
	    	        var state = data[i]['state'];
	    	        var ball  = data[i]['ball'];
	    	        var xd    = data[i]['xd'];
	    	        var yd    = data[i]['yd'];
	    	        var zd    = data[i]['zd'];
	    	        var xf    = data[i]['xf'];
	    	        var yf    = data[i]['yf'];
	    	        var zf    = data[i]['zf'];
                    data1[i] = {name:name,state:state,ball:ball,xd:xd,yd:yd,zd:zd,xf:xf,yf:yf,zf:zf};
           }
		   if(data.length != 10){
			   for(var j=0;j<(10-((data.length)%10));j++){               //補全最後一頁的空白行,使表格的長度保持不變
				   data1[j+data.length] = {name:" ",state:"",ball:"",xd:"",yd:"",zd:"",xf:"",yf:"",zf:""}; 
			   }
		   }
           var userOptions = {
                   "id":"kingTable",                                				//必須 表格id
                   "head":["時間","執行狀態","球頭狀態","X向位置/mm","Y向位置/mm","Z向位置/mm","X向承載力/Kg","Y向承載力/Kg","Z向承載力/Kg"],  //必須 thead表頭
                   "body":data1,                                    				//必須 tbody 後臺返回的資料展示
                   "foot":true,                                    					// true/false  是否顯示tfoot --- 預設false
                   "displayNum": 10,                               					//必須   預設 10  每頁顯示行數
                   "groupDataNum":6,                             					//可選    預設 10  組數
                   sort:false,                                    					// 點選表頭是否排序 true/false  --- 預設false
                   search:false,                                  					// 預設為false 沒有搜尋
                   lang:{
                       gopageButtonSearchText:"搜尋"
                   }
           }
           var cs = new KingTable(null,userOptions);
       }
   }); 

注意:只要前臺或者後臺有一處設定了返回json物件,就無需使用eval()方法或$.parseJSON()方法解析了,再解析就出錯。

總結:以上幾種方式,推薦使用第二種方式,方便且不易出錯。

五.eval()方法

 var json物件=eval('('+json資料+')');大括號括起來的內容被eval()執行後返回的是一個JSON物件。

eval函式的工作原理:eval函式會評估一個給定的含有JavaScript程式碼的字串,並且試圖去執行包含在字串裡的表示式或者一系列的合法的JavaScript語句。eval函式將把最後一個表示式或者語句所包含的值或引用作為返回值。

為什麼要 eval這裡要新增 “("("+data+")");//”呢?

原因在於:eval本身的問題。 由於json是以”{}”的方式來開始以及結束的,在JS中,它會被當成一個語句塊來處理,所以必須強制性的將它轉換成一種表示式。加上圓括號的目的是迫使eval函式在處理JavaScript程式碼的時候強制將括號內的表示式(expression)轉化為物件,而不是作為語句(statement)來執行。舉一個例子,例如物件字面量{},如若不加外層的括號,那麼eval會將大括號識別為JavaScript程式碼塊的開始和結束標記,那麼{}將會被認為是執行了一句空語句。