PHP的json_encode()函数与JSON对象

一、问题描述
这周搬砖的时候,前端通过ajax获取后端的数据后,照例用 对象.属性 的方式取值,然而结果总是总是不能如预期般展示在页面上。
先写个 demo 还原下场景:选中一个下拉框列表选项后,会在下拉框下面展示文字。
这是下拉框的html部分:

<html>
<head>
    <title>JSON DEMO</title>
    <meta charset="UTF-8">
</head>
<body>
    <select >
        <option value="">终端设备</option>
        <option value="1">PC Web</option>
        <!-- <option>...</option> -->
    </select>
    <div ></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对象的方法
后端

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字符串。

前端

"{test: 1}"    
//test是属性名称,必须加双引号

"{'test': 1}"    
//test是属性名称,必须用双引号(不能用单引号)

"'test'" 
//test是属性名称,必须用双引号(不能用单引号)

"undefined"    
//undefined 不能表示一个 JSON 字符串; null可以

"NaN" 
//NaN 不能表示一个 JSON 字符串; 用Infinity直接表示无限也是不允许的

四、疑惑
查了一下PHP的 json_encode()函数,PHP手册给出的结论是成功时返回字符串。
Return Values
Returns a JSON encoded string on success or FALSE on failure.

既然json_encode()函数返回的是字符串,为什么在项目中其他地方可以直接使用 对象.属性 的方式呢?