为什么json_encode后的JSON.parse无法工作?

5
为什么这个对我不起作用?
<script>
JSON.parse(<?php echo json_encode(array('test123', 'test456')); ?>);
</script>

我得到了这个错误:
语法错误:JSON.parse:在JSON数据之后出现意外的非空白字符。

1
你可能在php输出上遇到了一个错误。 - Pedro Lobito
你能发布一下 PHP 代码吗? - Sumner Evans
3个回答

6

PHP的json_encode函数可以生成一个字符串,但是它实际上是存在内存中的字符串,而不是 PHP 语法中的字符串,因此在使用 echo 输出时并没有被引号包裹。当输出到 JavaScript 代码环境中时,它打印出的是完全有效的 JSON,但是 JavaScript 解释器不会将其作为字符串看待,因为它没有被引号包裹。没有引号的话,JavaScript 将会把它视为用字面语法表示的数组(因为 JSON 借用了其子集的 JS 字面语法)。因此,尝试解析它将会抛出错误。

如果您的代码运行,则以下内容将实际显示在输出源中:

<script>
var obj = ["test123", "test456"];
</script>

作为一个数组,obj现在包含了许多JS文本语法。使用 JSON.parse 解析它将会导致错误。
可以把它想象成你在PHP中写的一句话,然后输出:
<?php
$sentence = 'I like beer.':
echo $sentence;
?>

这将产生以下输出:
I like beer.

注意不要包裹引号。现在,想象一下手动编写一块JSON并回显:

<?php
$json = '{"foo": "bar"}':
echo $json;
?>

这将输出:
{"foo": "bar"}

再次提醒,没有引号。将变量$json赋值会在PHP中产生与调用json_encode相同的字符串数据。因此,对您的调用输出进行回显也不需要引号。

现在,看看最后一个输出块 - 如果JavaScript引擎遇到这样的情况会怎么做?

因此,要使用JSON.parse进行解析,您需要在JS引擎解析期间将一些东西解释为字符串。如果您像这样使用单引号包装PHP:

<script>
var obj = '<?php echo json_encode(array('test123', 'test456')); ?>';
</script>

然后输出将是:
<script>
var obj = '["test123", "test456"]';
</script>

由于这是一个格式正确的字符串,因此现在它是JSON格式,可以传递给JSON.parse

注意:仅用单引号包装不安全,因为PHP编码的结构可能包含一个包含单引号的字符串。这将导致JavaScript语法错误。)

正如已经提到的,这一切都不必要-您可以将非引用JSON交给JS,并跳过解析,因为JS解释器将其解析并保存您的步骤。我只是想让您了解机制。希望我没有让你困惑... :(

JavaScript是唯一一种直接将JSON输出到不再是字符串的上下文中可能产生可行结果的语言。这是因为JSON语法从JavaScript字面语法的子集借鉴而来。

上下文是关键。例如,将JSON通过AJAX发送到JavaScript与您尝试将JSON提供给JavaScript的上下文是不同的。在AJAX的情况下,服务器对AJAX代码的响应已经是JS字符串了。而将PHP回显到JS代码中会生成需要由JS引擎解析的语法,因此需要引号使其成为字符串。


1
我会谨慎地将单引号简单地放在json_encode的输出周围。JSON的内容可能包含一个单引号,当打印时会提前终止字符串。如果你要将其包装在字符串中,你需要先转义任何单引号。 - Colin M
1
谢谢,这就是我在寻找的澄清。 - Recovering Nerdaholic

5

JSON已经是有效的JavaScript,因此在这里不需要使用JSON.parse。以下内容应该可以正常工作:

<script>
var obj = <?php echo json_encode(array('test123', 'test456')); ?>;
</script>

这将在页面上产生以下源代码(这是完全有效的JSON和Javascript):
<script>
var obj = ["test123", "test456"];
</script>
直接回答: 由于上述并没有技术性地回答你的问题,JSON.parse旨在处理字符串。你没有给它一个字符串,而是给了它一个对象(因为JSON是有效的JavaScript)。如果你实际上将值放在单引号中,则JSON.parse应该可以正常工作,但你需要确保它被正确转义(单引号内部的单引号会导致问题)。但在这种情况下,我建议避免将JSON作为字符串处理,因为这是不必要的。

哦...那我为什么要对每个通过AJAX响应传递的json_encode字符串运行JSON.parse呢?此外,它为什么还有效 - Recovering Nerdaholic
1
AJAX响应有点不同。当您收到AJAX响应时,响应作为字符串传递给客户端。必须对其进行JSON.parse(浏览器不会自动执行此操作)。然而,当您从PHP中使用echo输出某些内容时,就浏览器而言,这与在页面上硬编码var obj = ['test123', 'test456'];是相同的。它不知道它来自您的PHP脚本。 - Colin M

0

我认为你需要将 PHP 输出放在引号 "" 中间

试试这个:

<script>
    JSON.parse("<?php echo json_encode(array('test123', 'test456')); ?>");
</script>

这将会导致语法错误,因为JSON包含双引号,而您第一个添加的引号所开始的字符串会过早终止。 - JAAulde
我认为你应该重新考虑你正在做的事情。在PHP中混合Javascript或HTML是非常糟糕的做法。这不尊重MVC模式。 - Eduardo
虽然我同意使用PHP输出JavaScript是混乱、难以维护和容易出错的,但我不同意你说它不应该这样做的理由。MVC并不是编程中唯一的模式。在所有项目的所有上下文中都不必遵循这种模式。 - JAAulde

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接