PHP json_encode не избегает всех управляющих символов JSON

Есть ли причины, по которым функция 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 library json2.js, как и все остальные. Но если вы попытаетесь разобрать эту закодированную строку, она выдает ошибку:

<script type="text/javascript">

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

</script>

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

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

Ответ 1

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

<script type="text/javascript">

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

</script>

Ответ 2

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).

Ответ 3

Я до сих пор не понял никакого решения без 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);

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

Ответ 4

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

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

Ответ 5

Преобразование в PHP из PHP не должно быть проблемой. PHP json_encode делает правильную кодировку, но переинтерпретирует то, что внутри java script может вызвать проблемы. Как

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

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

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

чтобы обойти это: -

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

В) используйте строку 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   /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 script. Ввод строки JSON внутри двойных кавычек приведет к сбою синтаксического анализатора в марке атрибутов (что-то вроде { "id": "value" }). Никакое другое экранирование не требуется, если вы поместите строку как "литерал" и пусть JSON-парсер выполнит работу.

Ответ 6

Возможно, я слепой, но в вашем примере они сбежали. Что насчет

<script type="text/javascript">

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

</script>

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

Ответ 7

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

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

Ответ 8

$val = array ( "\n", "\ r" );

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

он удалит всю строку из строки json в php

Ответ 9

Просто добавление в ответ Greg: вывод json_encode() уже содержится в двойных кавычках ("), поэтому нет необходимости окружать они с кавычками снова:

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

Ответ 10

Управляющие символы не имеют особого значения в HTML, кроме новой строки в textarea.value. JSON_encode на PHP > 5.2 сделает это так, как вы ожидали.

Если вы просто хотите показать текст, вам не нужно идти за JSON. JSON предназначен для массивов и объектов в JavaScript (и индексированного и ассоциативного массива для PHP).

Если вам нужен фид строки для техасского тега:

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

Ответ 11

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

Источник script (ajax) примет массив и json_encode. Пример:

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

echo json_encode($return);

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

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

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

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

... может работать для вас.

Ответ 12

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

  • Запишите данные на входные данные и прочитайте их в JS:

    <input type="hidden" value="<?= htmlencode(json_encode($data)) ?>"/>
    
  • Используйте addlashes

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

Ответ 13

При использовании любой формы Ajax в Интернете отсутствует подробная документация для формата ответов, полученных с сервера CGI. Некоторые примечания здесь и записи в stackoverflow.com указывают, что новые строки в возвращаемых текстах или json-данных должны быть экранированы для предотвращения бесконечных циклов (зависаний) в преобразовании JSON (возможно, созданных путем бросания неперехваченного исключения), независимо от того, выполняется ли это вручную с помощью jQuery или вручную Javascript система или библиотека JSON разбор звонков.

В каждом случае, когда программисты публикуют эту проблему, представлены неадекватные решения (чаще всего заменяя \n на\\n на отправляющей стороне), и дело отбрасывается. Их неадекватность обнаруживается при передаче строковых значений, которые случайно вставляют управляющие escape-последовательности, такие как имена путей Windows. Пример: "C:\Chris\Roberts.php", который содержит управляющие символы ^ c и ^ r, что может привести к преобразованию JSON строки { "file": "C:\Chris\Roberts.php" } в цикл навсегда. Один из способов генерации таких значений преднамеренно пытается передать предупреждения и сообщения об ошибках PHP с сервера на клиент, разумную идею.

По определению Ajax использует HTTP-соединения за кулисами. Такие соединения передают данные с использованием GET и POST, оба из которых требуют кодирования отправленных данных, чтобы избежать неправильного синтаксиса, включая управляющие символы.

Это дает достаточно намека на то, что кажется решением (требуется больше тестирования): использовать rawurlencode на стороне PHP (отправки) для кодирования данных и unescape на стороне Javascript (получающей) для декодирования данные. В некоторых случаях вы будете применять их ко всем текстовым строкам, в других случаях вы будете применять их только к значениям внутри JSON.

Если эта идея окажется правильной, можно создать простые примеры, чтобы помочь программистам на всех уровнях решить эту проблему раз и навсегда.