【问题标题】:Why doesn't JSON.parse after json_encode doesn't work?为什么 json_encode 后 JSON.parse 不起作用?
【发布时间】:2014-04-18 02:30:15
【问题描述】:

为什么这对我不起作用?

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

我收到此错误:

SyntaxError: JSON.parse: unexpected non-whitespace character after JSON data

【问题讨论】:

  • 您可能在 php 输出中遇到错误。
  • 能把PHP代码贴出来吗?

标签: javascript php json


【解决方案1】:

PHP 的json_encode 生成一个字符串,但它是内存中的实际字符串,而不是 PHP 语法中的字符串,所以当echoed 时它没有用引号括起来。当回显到 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 引擎解析的语法,因此需要引号将其变为字符串。

【讨论】:

  • 我会谨慎对待在json_encode 的输出周围天真地粘贴单引号。 JSON 的内容可能包含一个单引号,在打印时会提前终止字符串。如果要将其包装在字符串中,则需要先转义任何单引号。
  • 谢谢,这是我要找的说明。
【解决方案2】:

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_encoded 字符串上运行 JSON.parse?此外,为什么它会工作
  • AJAX 响应有点不同。当您收到 AJAX 响应时,响应将作为字符串传递给客户端。那必须是JSON.parsed(浏览器不会自动为您执行此操作)。但是,当您从 PHP 中 echo 输入某些内容时,就浏览器而言,这与在页面上硬编码 var obj = ['test123', 'test456']; 相同。它不知道它来自您的 PHP 脚本。
【解决方案3】:

我认为您必须将 PHP 输出放在引号“”之间

试试这个:

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

【讨论】:

  • 这将导致语法错误,因为 JSON 包含双引号,并且由您添加的第一个引号开始的字符串将提前终止。
  • 我认为你应该重新考虑你在做什么。将 PHP 与 Javascript 或 HTML 混合使用是一种非常糟糕的做法。这不尊重 MVC 模式
  • 虽然我同意用 PHP 输出 JavaScript 是混乱的、不可维护的并且非常容易出错,但我不同意你说不应该这样做的理由。 MVC 并不是编程中的唯一模式。在所有项目的所有上下文中,没有人会被这种模式束缚。
猜你喜欢
  • 2018-03-05
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 2021-08-02
  • 1970-01-01
  • 2015-03-31
  • 2014-01-13
  • 1970-01-01
相关资源
最近更新 更多