一、問題描述
這周搬磚的時候,前端通過ajax獲取後端的數據後,照例用 對象.屬性
的方式取值,然而結果總是總是不能如預期般展示在頁面上。
先寫個 demo 還原下場景:選中一個下拉框列表選項後,會在下拉框下面展示文字。
這是下拉框的html部分:
<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
$onLines = [
1 => 'PC Web',
2 => 'iPad HD',
5 => 'Touch'
];
echo json_encode(['data' => $onLines]);
JS代碼如下:
<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對象!
success: function(result) {
console.log(result);
console.log(result.data);
console.log(typeof result);
}
二、解決方法
找到問題就好辦了,只需要把 json 字符串轉成 json 對象就好了,最簡單的辦法是 JSON.parse()
。
success: function(result) {
var onlineDevices = JSON.parse(result).data;
# code ...
}
三、總結
1、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對象的形式很像,但前者比後者多了一對引號,其內容包含在引號裏了。調試臺的結果如下:
2、json字符串轉爲json對象的方法
後端
設置header頭中的內容類型,將 Content-Type 設置爲 text/json。
header('Content-Type:text/json;charset=utf-8');
注:前端直接處理即可,不需要 JSON.parse() 處理。
但項目中用的是框架,所有的PHP文件(業務層)均沒有顯式設置 header,雖然在demo中此方法有效,可依然不明白爲什麼別的地方返回的是json對象,而這裏返回的卻是json字符串了。- 強制類型轉換(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字符串,否則會報錯。
四、疑惑
查了一下PHP的 json_encode()函數,PHP手冊給出的結論是成功時返回字符串。
Return Values
Returns a JSON encoded string on success or FALSE on failure.
既然json_encode()函數返回的是字符串,爲什麼在項目中其他地方可以直接使用 對象.屬性
的方式呢?