JavaScript解码包含编码字符串的JSON字符串

3
我有以下的PHP代码:
    $foo = new stdClass();
    $foo->test='hello world';
    $bar = new stdClass();
    $bar->foo = json_encode($foo);
    $encoded_string = json_encode($bar);

$encoded_string 包含:

{"foo":"{\"test\":\"hello world\"}"}

我希望能够从 JavaScript 中解析这个字符串(例如使用 jQuery 的 $.parseJSON 方法):
var data = $.parseJSON('{"foo":"{\"test\":\"hello world\"}"}');
console.log(data);

我希望能够记录类似以下内容:

Object {foo: '{"test":"hello world"}'}

当我运行它时(使用chromium),会出现“意外的标记t”错误。

如何在Javascript中解析这个JSON字符串?如果有人想尝试,这里是一个小例子

5个回答

6
您遇到的问题是,json_encode 的输出并不适合直接作为 JavaScript 中的字符串使用。 json_encode 输出一个可用的 JavaScript 对象:
<?php
$foo = new stdClass();
$foo->test='hello world';
$bar = new stdClass();
$bar->foo = json_encode($foo);
$encoded_string = json_encode($bar);
?>
var a = <?php $encoded_string ?>;
console.log(a.foo); // produces '{"test":"hello world"}'

如果您想要无谓地解析字符串值的JSON输出,只需对$encoded_string进行双重编码即可:

<?php
$foo = new stdClass();
$foo->test='hello world';
$bar = new stdClass();
$bar->foo = json_encode($foo);
$encoded_string = json_encode(json_encode($bar));
?>
var aStr = <?php $encoded_string ?>;
var a = JSON.parse(aStr);
console.log(a.foo); //same as before

当然,您应该避免使用服务器端语言来生成JavaScript代码,而是将数据设置为data-*属性或作为可以通过AJAX请求的JSON源。
当从服务器(或属性)请求数据时,它将作为经过适当转义的JavaScript字符串呈现,这就是需要使用JSON.parse解析对象的地方。

2

您的代码应该是:

$foo = new stdClass();
$foo->test='hello world';
$bar = new stdClass();
$bar->foo = $foo;
$encoded_string = json_encode($bar);

只需在最后进行一次JSON编码,然后在另一端开始时进行一次解码即可。
关于jsfiddle,您没有考虑到字符串文字在成为“JavaScript内存中的字符串”之前会通过额外的解码层。在这种情况下设置字符串文字的正确方法是(JS-JSON-JSON):
data = $.parseJSON('{"foo":"{\\\"test\\\":\\\"hello world\\\"}"}');
console.log($.parseJSON(data.foo));

只需简单地反转您所做的编码步骤即可。 http://jsfiddle.net/Jmjjp/2/

1
问题是在JSON中进行双重编码。如果需要将数据保留为字符串,您想要的解决方案是: $bar->foo = addslashes(json_encode($foo));

将编码和解码视为将项目放置在嵌套的盒子中。addslashes不是将字符串编码以将其存储在另一个盒子中的适当函数。可以简单地调用json_encode(json_encode($foo)),但真正的根本问题是为什么首先需要这样做。 - zzzzBov
同意。Pinoniq的回答应该足够了。首先应该处理“来自不同来源的任意数据,可能已经是JSON编码,也可能不是”的数据,以检查正在传输的数据,然后再进行编码(可能需要重新编码)。 - scum

0

你需要转义斜杠以保护内部引号:

JSON.parse('{"foo":"{\\"test\\":\\"hello world\\"}"}');
// == Object {foo: '{"test":"hello world"}'}

0

代码返回了应该返回的内容。

当在json_encode中使用$bar时,$bar->foo是一个字符串。为了产生正确的输出,这个字符串被转义了。

$bar->foo = json_encode($foo);

应该是$bar->foo = $foo



我的问题是$bar包含json编码的属性。函数是正确的,但我该如何在JavaScript中获取对象呢? - periklis
我不想解析内部编码的字符串(在这个例子中是$foo);我希望它保持原样,只获取“外部”对象。 - periklis
我不明白问题出在哪里,也不知道为什么我的答案不能解决你的问题 :/ - Pinoniq
Pinoniq 是正确的。问题是 JSON 双重编码。如果您需要将数据保留为字符串,您想要的解决方案是 $bar->foo = addslashes(json_encode($foo)); - scum
@Pinoniq,因为我无法控制字符串$foo。它是来自不同来源的任意数据,可能已经进行了JSON编码,也可能没有。您的解决方案基于我可以绕过对foo的编码这一假设,但那只是一个例子,所以您并没有回答问题本身:一个包含已编码属性的json编码对象将如何解码? - periklis
哦,这种情况下我的回答就不算是一个回答了 :) - Pinoniq

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