简体   繁体   中英

Javascript decode JSON string which contains an encoded string

I have the following PHP code:

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

The $encoded_string contains:

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

I want to parse this string from javascript (using jQuery's $.parseJSON for example):

var data = $.parseJSON('{"foo":"{\"test\":\"hello world\"}"}');
console.log(data);

I would expect something like the following to be logged:

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

But I get an Unexpected token t error when running it (using chromium)

How can I parse this json string in Javascript? Here's a fiddle if anyone wants to try.

The problem that you're running into is that the output of json_encode is not meant to be used directly as a string in JavaScript.

json_encode outputs a usable JavaScript object:

<?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"}'

If you want to needlessly parse the JSON output from a string value, you simply need to double encode $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

Of course, you should avoid using server side languages to generate JavaScript code, instead set up the data as either a data-* attribute or as a JSON source that can be requested with AJAX.

When the data is requested from the server (or from the attribute) it will be as a properly escaped JavaScript string, which is where JSON.parse will be necessary to parse the object.

Your code should be

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

Just json encode once at the end, and decode once at the beginning at the other end.


As for the jsfiddle, you are not considering that the string literals go through additional decoding layer before they become "strings in javascript memory".

The correct way to setup the string literal in this case is (JS-JSON-JSON):

data = $.parseJSON('{"foo":"{\\\"test\\\":\\\"hello world\\\"}"}');
console.log($.parseJSON(data.foo));

And simply reversing the encoding steps you did works. http://jsfiddle.net/Jmjjp/2/

The problem is double encoding as JSON. The solution you want if you need to retain the data as a string is

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

The code returns exactly what it should return.

when json_encodein $bar, $bar->foo is a string. this string is escaped to produce a correct output.

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

should be $bar->foo = $foo

you need to escape the slashes protecting the inner quotes:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM