【问题标题】:Javascript decode JSON string which contains an encoded stringJavascript解码包含编码字符串的JSON字符串
【发布时间】:2013-06-15 05:56:59
【问题描述】:

我有以下 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"}'}

但我在运行它时遇到Unexpected token t 错误(使用铬)

如何在 Javascript 中解析这个 json 字符串? Here's a fiddle如果有人想试试。

【问题讨论】:

    标签: php javascript jquery json escaping


    【解决方案1】:

    代码准确地返回它应该返回的内容。

    当json_encodein $bar 时,$bar->foo 是一个字符串。这个字符串被转义以产生正确的输出。

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

    应该是$bar->foo = $foo

    【讨论】:

    • 我的问题是 $bar 包含 json_encoded 属性。功能正确;我如何在 javascript 中获取对象?
    • 我不希望内部编码字符串未解析(本例中为 $foo);我希望它保持原样,只得到“外部”对象
    • 我不明白问题是什么,或者为什么我的回答不能解决你的问题:/
    • Pinoniq 是正确的。问题是双重编码为​​ JSON。如果您需要将数据保留为字符串,您想要的解决方案是$bar->foo = addslashes(json_encode($foo));
    • @Pinoniq 因为我无法控制字符串 $foo。它是来自不同来源的任意数据,可能已经或可能尚未经过 json 编码。您的解决方案基于我可以绕过编码 foo 的假设,但这只是一个示例,因此您本身并没有回答问题:包含已编码属性的 json_encoded 对象,它将如何被解码?跨度>
    【解决方案2】:

    您需要转义保护内引号的斜线:

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

    【讨论】:

      【解决方案3】:

      问题是双重编码为​​ JSON。如果您需要将数据保留为字符串,您想要的解决方案是

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

      【讨论】:

      • 将编码和解码想象成将项目放置在嵌套框中。 addslashes 不是对字符串进行编码以将其存储在另一个框中的适当函数。可以简单地调用json_encode(json_encode($foo)),但真正的根本问题是为什么首先需要这样做。
      • 同意。 Pinoniq 的回答应该足够了。应该首先处理“来自不同来源的任意数据,可能已经或可能尚未进行 json 编码”,以检查在编码之前遇到的数据(可能再次)。
      【解决方案4】:

      你的代码应该是

      $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/

      【讨论】:

        【解决方案5】:

        您遇到的问题是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-* attribute 或可以使用 AJAX 请求的 JSON 源。

        当从服务器(或属性)请求数据时,它将作为正确转义的 JavaScript 字符串,这是解析对象所必需的JSON.parse

        【讨论】:

        • 这是有道理的,显然是处理json“字符串”的正确方法;感谢您的精彩解释。
        猜你喜欢
        • 2019-04-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多