Json_encode PHP не экранирует все управляющие символы JSON - PullRequest
26 голосов
/ 26 июня 2009

Есть ли причины, по которым функция PHP json_encode не экранирует все JSON управляющие символы в строке?

Например, давайте возьмем строку, которая занимает две строки и содержит управляющие символы (\ r \ n "/ \):

<?php
$s = <<<END
First row.
Second row w/ "double quotes" and backslash: \.
END;

$s = json_encode($s);
echo $s;
// Will output: "First row.\r\nSecond row w\/ \"double quotes\" and backslash: \\."
?>

Обратите внимание, что символы возврата каретки и перевода строки не экранированы. Почему?

Я использую jQuery в качестве своей библиотеки JS, и ее функция $ .getJSON () прекрасно работает, когда вы полностью, 100% доверяете входящим данным. В противном случае я использую библиотеку JSON.org json2.js, как и все остальные. Но если вы попытаетесь разобрать эту закодированную строку, она выдаст ошибку:

<script type="text/javascript">

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

</script>

И вы не можете получить данные! Если вы удалите или удалите \ r \ n "и \ в этой строке, то JSON.parse () не выдаст ошибку.

Существует ли какая-либо хорошая, хорошая функция PHP для экранирования управляющих символов. Простое str_replace с массивами поиска и замены не будет работать.

Ответы [ 13 ]

28 голосов
/ 01 сентября 2010
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;
  }

Я использую вышеупомянутую функцию, которая экранирует обратную косую черту (должна быть первой в массивах) и должна работать с formfeeds и backspaces (я не думаю, что \f и \b поддерживаются в PHP).

12 голосов
/ 26 июня 2009

D'oh - вам нужно двойное кодирование: JSON.parse, конечно, ожидает строку:

<script type="text/javascript">

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

</script>
4 голосов
/ 17 августа 2010

Я до сих пор не нашел никакого решения без str_replace ..

Попробуйте этот код.

$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);

Надеюсь, это поможет ...

3 голосов
/ 25 августа 2010
$search = array("\n", "\r", "\u", "\t", "\f", "\b", "/", '"');
$replace = array("\\n", "\\r", "\\u", "\\t", "\\f", "\\b", "\/", "\"");
$encoded_string = str_replace($search, $replace, $json);

Это правильный путь

2 голосов
/ 02 февраля 2012

Преобразование туда и обратно из PHP не должно быть проблемой. Json_encode PHP выполняет правильную кодировку, но переосмысление этого внутри java-скрипта может вызвать проблемы. Нравится

1) исходная строка - [строка с nnn символом новой строки в нем] (где nnn - фактический символ новой строки)

2) json_encode преобразует это в [строка с новой строкой "\\ n"] (управляющий символ преобразован в "\\ n" - литерал "\ n"

3) Однако, когда вы печатаете это снова в литеральной строке, используя php echo, тогда «\\ n» интерпретируется как «\ n», и это вызывает душевную боль. Потому что JSON.parse будет понимать печатную букву "\ n" как символ новой строки - управляющий символ (nnn)

так, чтобы обойти это: -

A) Сначала закодируйте объект json в php с помощью json_enocde и получите строку. Затем запустите его через фильтр, который делает его безопасным для использования внутри html и java-скриптов.

В) используйте строку JSON из PHP как «литерал» и поместите ее в одинарные кавычки вместо двойных.


<?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>

Поместите строку в одинарные кавычки в сценарии Java. Помещение строки JSON в двойные кавычки может привести к сбою синтаксического анализа в маркерах атрибута (что-то вроде {"id": "value"}). Никакого другого экранирования не требуется, если вы поставили строку как «литерал» и позволили JSON-анализатору сделать всю работу.

1 голос
/ 26 июня 2009

Может быть, я слепой, но в вашем примере они Бежали. Как насчет

<script type="text/javascript">

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

</script>

(обратите внимание на различные цитаты)

0 голосов
/ 14 сентября 2017

Существует 2 решения, если не используется AJAX:

  1. Записать данные во входные данные как и прочитать в JS:

    <input type="hidden" value="<?= htmlencode(json_encode($data)) ?>"/>
    
  2. Использовать addlashes

    var json = '<?= addslashes(json_encode($data)) ?>';
    
0 голосов
/ 03 мая 2017
$val = array("\n","\r");

$string = str_replace($val, "", $string);

Он удалит все символы новой строки из строки json в PHP

0 голосов
/ 13 июля 2014

Это то, что я использую лично, и это никогда не работало. Изначально были похожие проблемы.

Исходный скрипт (ajax) возьмет массив и json_encode его. Пример:

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

echo json_encode($return);

Мой javascript выполнит вызов AJAX и получит эхо-сигнал "json_encode ($ return)" в качестве входных данных, и в сценарии я буду использовать следующее:

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

с возвращаемым значением "msg". Итак, для вас что-то вроде ...

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

... может работать на вас.

0 голосов
/ 21 февраля 2014

Я не совсем понимаю, как работает var_export, поэтому я буду обновляться, если у меня возникнут проблемы, но мне кажется, что это работает:

<script>
    window.things = JSON.parse(<?php var_export(json_encode($s)); ?>);
</script>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...