0

Here is my php:

$response = array(
    'errors' => $this->errors,
    'orders_fulfilled' => $this->orders_fulfilled,
);
echo '<pre>$response: ' . print_r($response, true) . '</pre>';

$json = json_encode($response, JSON_HEX_APOS);
echo '<pre>$json: ' . print_r($json, true) . '</pre>';

This shows the following output:

$response: Array
(
    [errors] => Array
        (
            [0] => Error text

        )

    [orders_fulfilled] => 0
)

$json: {"errors":["Error text\n"],"orders_fulfilled":0}

QUESTION:

Why does php's json_encode() create unescaped \n characters out of actual newlines in the source php array, when they are not valid in the json string?

I see in this accepted answer the suggestion is to escape the source newlines, i.e. convert from \n to \\n. So why should PHP's json_encode() not be doing so here? As it stands it is directly creating a json string that chokes JSON.Parse() in javascript. For instance, try running this in console:

JSON.parse('{"errors":["Error text\n"],"orders_fulfilled":0}');

VM1628:1 Uncaught SyntaxError: Unexpected token in JSON at position 22 at JSON.parse () at :1:6

If I add a slash to escape the newline or remove it altogether, the error is gone.

Is there a flag for json_encode() that I should be using to handle escaping of special/control characters this that I have not seen in the PHP manual?

3
  • This is not a Shopify issue, strictly a question about php's json_encode and usage in conjunction with JSON.parse Commented Dec 15, 2016 at 15:39
  • Question do you parse the $json in the html (print $json)? Because then the linebreak is noticed by the browser! Or how do you test the JSON.parse('{"errors":["Sh line ? Commented Dec 15, 2016 at 15:42
  • If you can't control outputs of error, just add addslashes manually in your $response Commented Dec 15, 2016 at 16:01

1 Answer 1

6

The output of json_encode is fine.

The problem is that when you try to convert it to a JavaScript string literal by wrapping it with ', the \n gets parsed as a new line in the JS string.

When you try to parse that string as JSON, it has a real new line in it.

To convert to a JavaScript string, you also have to escape any special characters in it.

Since JSON is (more-or-less) a subset of JavaScript, json_encode will do that:

var json = <?php json_encode(json_encode($foo)); ?>;
var obj = JSON.parse(json);
console.log(obj);

… but that's a silly approach.

Just skip the bit where you treat it as JSON and just treat it as JavaScript.

var obj = <?php json_encode($foo); ?>;
console.log(obj);
Sign up to request clarification or add additional context in comments.

4 Comments

ah I see, so this is being seen as an actual line-break appearing in the middle of a json value thus causing an "unterminated string literal" error?
I have since managed to verify that indeed the \n is perfectly valid within the json string literal
\n is valid in a JavaScript string. \n is valid in a JSON string. A \n in the expression of a JSON string as a JavaScript string will put a new line in the JSON string. A new line is not valid in a JSON string. To see this run '{"errors":["Error text\n"],"orders_fulfilled":0}' directly in your browser's JS console. Then copy the result, including the line break, into JSON Lint.
perfect demo of the problem right there! I am primarily a PHP head and my brain is thus used to only seeing strings in double quotes interpret the \n, whereas in single quotes the \n is taken literally. I didn't realise that a JavaScript string would interpret the \n as a literal new line (like in a PHP double quoted string), hence the flaw in my understanding.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.