[ACCEPTED]-PHP's json_encode does not escape all JSON control characters-json

Accepted answer
Score: 30
function escapeJsonString($value) {
    # list from www.json.org: (\b backspace, \f formfeed)    
    $escapers =     array("\\",     "/",   "\"",  "\n",  "\r",  "\t", "\x08", "\x0c");
    $replacements = array("\\\\", "\\/", "\\\"", "\\n", "\\r", "\\t",  "\\f",  "\\b");
    $result = str_replace($escapers, $replacements, $value);
    return $result;
  }

I'm using the above function which escapes 3 a backslash (must be first in the arrays) and 2 should deal with formfeeds and backspaces 1 (I don't think \f and \b are supported in PHP).

Score: 13

D'oh - you need to double-encode: JSON.parse 1 is expecting a string of course:

<script type="text/javascript">

JSON.parse(<?php echo json_encode($s) ?>);

</script>
Score: 4

I still haven't figured out any solution 1 without str_replace..

Try this code.

$json_encoded_string = json_encode(...);
$json_encoded_string = str_replace("\r", '\r', $json_encoded_string);
$json_encoded_string = str_replace("\n", '\n', $json_encoded_string);

Hope that helps...

Score: 3
$search = array("\n", "\r", "\u", "\t", "\f", "\b", "/", '"');
$replace = array("\\n", "\\r", "\\u", "\\t", "\\f", "\\b", "\/", "\"");
$encoded_string = str_replace($search, $replace, $json);

This is the correct way

0

Score: 2

Converting to and fro from PHP should not 26 be an issue. PHP's json_encode does proper 25 encoding but reinterpreting that inside 24 java script can cause issues. Like

1) original 23 string - [string with nnn newline in it] (where 22 nnn is actual newline character)

2) json_encode 21 will convert this to [string with "\\n" newline 20 in it] (control character converted to "\\n" - Literal 19 "\n"

3) However when you print this again 18 in a literal string using php echo then 17 "\\n" is interpreted as "\n" and that causes 16 heartache. Because JSON.parse will understand 15 a literal printed "\n" as newline - a control 14 character (nnn)

so to work around this: -

A) First 13 encode the json object in php using json_enocde 12 and get a string. Then run it through a 11 filter that makes it safe to be used inside 10 html and java script.

B) use the JSON string 9 coming from PHP as a "literal" and put it 8 inside single quotes instead of double quotes.


<?php
       function form_safe_json($json) {
            $json = empty($json) ? '[]' : $json ;
            $search = array('\\',"\n","\r","\f","\t","\b","'") ;
            $replace = array('\\\\',"\\n", "\\r","\\f","\\t","\\b", "&#039");
            $json = str_replace($search,$replace,$json);
            return $json;
        }


        $title = "Tiger's   /new \\found \/freedom " ;
        $description = <<<END
        Tiger was caged
        in a Zoo 
        And now he is in jungle
        with freedom
    END;

        $book = new \stdClass ;
        $book->title = $title ;
        $book->description = $description ;
        $strBook = json_encode($book);
        $strBook = form_safe_json($strBook);

        ?>


    <!DOCTYPE html>
    <html>

        <head>
            <title> title</title>

            <meta charset="utf-8">


            <script type="text/javascript" src="/3p/jquery/jquery-1.7.1.min.js"></script>


            <script type="text/javascript">
                $(document).ready(function(){
                    var strBookObj = '<?php echo $strBook; ?>' ;
                    try{
                        bookObj = JSON.parse(strBookObj) ;
                        console.log(bookObj.title);
                        console.log(bookObj.description);
                        $("#title").html(bookObj.title);
                        $("#description").html(bookObj.description);
                    } catch(ex) {
                        console.log("Error parsing book object json");
                    }

                });
            </script>

        </head>

         <body>

             <h2> Json parsing test page </h2>
             <div id="title"> </div>
             <div id="description"> </div>
        </body>
    </html>

Put 7 the string inside single quote in java script. Putting 6 JSON string inside double quotes would cause 5 the parser to fail at attribute markers 4 (something like { "id" : "value" } ). No 3 other escaping should be required if you 2 put the string as "literal" and let JSON 1 parser do the work.

Score: 1

I don't fully understand how var_export 2 works, so I will update if I run into trouble, but 1 this seems to be working for me:

<script>
    window.things = JSON.parse(<?php var_export(json_encode($s)); ?>);
</script>
Score: 0

Maybe I'm blind, but in your example they 2 ARE escaped. What about

<script type="text/javascript">

JSON.parse("<?php echo $s ?>");  // Will throw SyntaxError 

</script>

(note different 1 quotes)

Score: 0

Just an addition to Greg's response: the output 3 of json_encode() is already contained in double-quotes 2 ("), so there is no need to surround them 1 with quotes again:

<script type="text/javascript">
    JSON.parse(<?php echo $s ?>);
</script>
Score: 0

Control characters have no special meaning 7 in HTML except for new line in textarea.value 6 . JSON_encode on PHP > 5.2 will do it like 5 you expected.

If you just want to show text 4 you don't need to go after JSON. JSON is 3 for arrays and objects in JavaScript (and 2 indexed and associative array for PHP).

If 1 you need a line feed for the texarea-tag:

$s=preg_replace('/\r */','',$s);
echo preg_replace('/ *\n */','&#13;',$s);
Score: 0

This is what I use personally and it's never 8 not worked. Had similar problems originally.

Source 7 script (ajax) will take an array and json_encode 6 it. Example:

$return['value'] = 'test';
$return['value2'] = 'derp';

echo json_encode($return);

My javascript will make an AJAX 5 call and get the echoed "json_encode($return)" as 4 its input, and in the script I'll use the 3 following:

myVar = jQuery.parseJSON(msg.replace(/&quot;/ig,'"'));

with "msg" being the returned 2 value. So, for you, something like...

var msg = '<?php echo $s ?>';
myVar = jQuery.parseJSON(msg.replace(/&quot;/ig,'"'));

...might 1 work for you.

Score: 0

There are 2 solutions unless AJAX is used:

  1. Write 2 data into input like and read it in JS:

    <input type="hidden" value="<?= htmlencode(json_encode($data)) ?>"/>
    
  2. Use 1 addslashes

    var json = '<?= addslashes(json_encode($data)) ?>';
    

More Related questions