1、問題描述 這周搬磚的時候,前端經過ajax獲取後端的數據後,照例用 對象.屬性
的方式取值,然而結果老是老是不能如預期般展現在頁面上。 先寫個 demo 還原下場景:選中一個下拉框列表選項後,會在下拉框下面展現文字。 這是下拉框的html部分:javascript
<html> <head> <title>JSON DEMO</title> <meta charset="UTF-8"> </head> <body> <select id="device"> <option value="">終端設備</option> <option value="1">PC Web</option> <!-- <option>...</option> --> </select> <div id="tip"></div> </body> </html>
PHP代碼以下:用來返回數據(接收、處理過程略)php
<?php $onLines = [ 1 => 'PC Web', 2 => 'iPad HD', 5 => 'Touch' ]; echo json_encode(['data' => $onLines]);
JS代碼以下:html
<script type="text/javascript"> $("#device").change(function() { var selectVal = $("#device").val(); if (selectVal == '') { $("#tip").html(''); return; } # code... ajax 部分的代碼見下 }); </script>
ajax 部分的代碼用來接收從後端(PHP)傳過來的數據,並處理。前端
$.ajax({ url: 'device.php', type: 'post', dateType: 'json', data: { device: selectVal }, success: function(result) { var onlineDevices = result.data; var onlineTip = '容許' + onlineDevices[selectVal] + '類型的2臺設備同時在線。'; $("#tip").html(''); $("#tip").append(onlineTip); } });
使用 console.log
在控制檯輸出結果,以下圖所示,能夠看到後端返回的數據是沒有問題的, 再使用 typeof
查看返回的數據類型,前端收到的數據是JSON字符串!而不是JSON對象!java
success: function(result) { console.log(result); console.log(result.data); console.log(typeof result); }
2、解決方法 找到問題就好辦了,只須要把 json 字符串轉成 json 對象就行了,最簡單的辦法是 JSON.parse()
。ajax
success: function(result) { var onlineDevices = JSON.parse(result).data; # code ... }
3、總結 一、json字符串和json對象的區別json
// JSON 字符串 var str1 = '{"data":{"1":"PC Web","2":"iPad HD","5":"Touch"}}'; // JSON 對象 var str2 = {"data":{"1":"PC Web","2":"iPad HD","5":"Touch"}}; console.log(str1); console.log(typeof str1); console.log(str2); console.log(typeof str2);
能夠看到json字符串和json對象的形式很像,但前者比後者多了一對引號,其內容包含在引號裏了。調試臺的結果以下: 後端
二、json字符串轉爲json對象的方法 後端數組
-
設置header頭中的內容類型,將 Content-Type 設置爲 text/json。
header('Content-Type:text/json;charset=utf-8');
注:前端直接處理便可,不須要 JSON.parse() 處理。 但項目中用的是框架,全部的PHP文件(業務層)均沒有顯式設置 header,雖然在demo中此方法有效,可依然不明白爲何別的地方返回的是json對象,而這裏返回的倒是json字符串了。app -
強制類型轉換(object) 此方法無效! 若是將一個對象轉換成對象,它將不會有任何變化。若是其它任何類型的值被轉換成對象,內置標準類 stdClass 的一個實例將被創建。 以上面的數組爲例,強制類型轉換的結果以下:
var_dump((object)['data' => $onLines]); // 結果以下: object(stdClass)#1 (1) { ["data"]=> array(3) { [1]=> string(6) "PC Web" [2]=> string(7) "iPad HD" [5]=> string(5) "Touch" } }
而json_encode((object)['data' => $onLines]);
獲得的仍是json字符串。
前端
- var obj = JSON.parse(str); JSON.parse()方法,必須保證傳入的是json字符串,若是是json對象會報錯。
- var obj = jQuery.parseJSON(str); parseJSON()方法是jQuery方法,僅支持標準json格式,不然會報錯。 下面這些是無效的 JSON 字符串:
"{test: 1}" //test是屬性名稱,必須加雙引號 "{'test': 1}" //test是屬性名稱,必須用雙引號(不能用單引號) "'test'" //test是屬性名稱,必須用雙引號(不能用單引號) "undefined" //undefined 不能表示一個 JSON 字符串; null能夠 "NaN" //NaN 不能表示一個 JSON 字符串; 用Infinity直接表示無限也是不容許的
- var obj = eval('(' + str + ')'); eval()方法是js方法,也是必須保證傳入的是json字符串,不然會報錯。
4、疑惑 查了一下PHP的 json_encode()函數,PHP手冊給出的結論是成功時返回字符串。 Return Values Returns a JSON encoded string on success or FALSE on failure.
既然json_encode()函數返回的是字符串,爲何在項目中其餘地方能夠直接使用 對象.屬性
的方式呢?
後記 更新於2019-02-25 今天不死心,又研究了一下,還問了一個朋友,對方提醒估計大機率是編碼和頭的設置有問題,而後我逐行查代碼,發現 ajax 部分的dataType
我寫成了dateType
,一字之差~ 噢,天啊,太丟人了!之後絕對不能再犯這麼二的錯誤了!