为什么这对我不起作用?
<script>
JSON.parse(<?php echo json_encode(array('test123', 'test456')); ?>);
</script>
我收到此错误:
SyntaxError: JSON.parse: unexpected non-whitespace character after JSON data
答案 0 :(得分: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作为字符串处理,因为在这种情况下它是不必要的。
答案 1 :(得分:5)
PHP的json_encode
生成一个字符串,但它是内存中的实际字符串,而不是PHP语法中的字符串,因此在echo
编辑时它不会包含在引号中。当回显到JavaScript代码的上下文中时,它会打印出完全有效的JSON,但JS解释器不会将其视为字符串,因为它不包含在引号中。没有它们,JS会看到一个用文字语法表示的数组(因为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在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文字语法的一个子集。
上下文就是这里的一切。例如,通过AJAX将JSON发送到JavaScript与您尝试向JavaScript提供一些JSON时显示的上下文不同。在AJAX的情况下,服务器对AJAX代码的响应已经是内存中的JS字符串。将PHP回显到JS代码中会产生JS引擎解析的语法,因此需要引号使其成为字符串。
答案 2 :(得分:0)
我认为你必须将PHP输出放在引号&#34;&#34;
之间试试这个:
<script>
JSON.parse("<?php echo json_encode(array('test123', 'test456')); ?>");
</script>