Я пытаюсь подражать json_encode
флаги битовой маски, реализованные в PHP 5.3.0, вот являются строкой, которую я имею:
$s = addslashes('O\'Rei"lly'); // O\'Rei\"lly
Выполнение json_encode($s, JSON_HEX_APOS | JSON_HEX_QUOT)
производит следующее:
"O\\\u0027Rei\\\u0022lly"
И я в настоящее время делаю это в версиях PHP, более старых, чем 5.3.0:
str_replace(array('\\"', "\\'"), array('\\u0022', '\\\u0027'), json_encode($s))
or
str_replace(array('\\"', '\\\''), array('\\u0022', '\\\u0027'), json_encode($s))
Который правильно производит тот же результат:
"O\\\u0027Rei\\\u0022lly"
Я испытываю затруднения при понимании, почему я должен заменить одинарные кавычки ('\\\''
или даже "\\'"
[окружая кавычки, исключенные]) с '\\\u0027'
и не просто '\\u0027'
.
Вот код, который я испытываю затруднения при портировании на PHP <5.3:
if (get_magic_quotes_gpc() && version_compare(PHP_VERSION, '6.0.0', '<'))
{
/* JSON_HEX_APOS and JSON_HEX_QUOT are availiable */
if (version_compare(PHP_VERSION, '5.3.0', '>=') === true)
{
$_GET = json_encode($_GET, JSON_HEX_APOS | JSON_HEX_QUOT);
$_POST = json_encode($_POST, JSON_HEX_APOS | JSON_HEX_QUOT);
$_COOKIE = json_encode($_COOKIE, JSON_HEX_APOS | JSON_HEX_QUOT);
$_REQUEST = json_encode($_REQUEST, JSON_HEX_APOS | JSON_HEX_QUOT);
}
/* mimic the behaviour of JSON_HEX_APOS and JSON_HEX_QUOT */
else if (extension_loaded('json') === true)
{
$_GET = str_replace(array(), array('\\u0022', '\\u0027'), json_encode($_GET));
$_POST = str_replace(array(), array('\\u0022', '\\u0027'), json_encode($_POST));
$_COOKIE = str_replace(array(), array('\\u0022', '\\u0027'), json_encode($_COOKIE));
$_REQUEST = str_replace(array(), array('\\u0022', '\\u0027'), json_encode($_REQUEST));
}
$_GET = json_decode(stripslashes($_GET));
$_POST = json_decode(stripslashes($_POST));
$_COOKIE = json_decode(stripslashes($_COOKIE));
$_REQUEST = json_decode(stripslashes($_REQUEST));
}
PHP-строка
'O\'Rei"lly'
- это просто способ PHP получить литеральное значение
O'Rei"lly
в строку, которую можно использовать. Вызов addslashes
на этой строке изменяет ее на буквальные 11 символов
O\'Rei\"lly
т.е. strlen(addslashes('O\'Rei "lly')) == 11
Это и есть значение, которое передается в json_escape
.
В JSON обратная косая черта является управляющим символом, поэтому ее нужно экранировать, т.е.
\
должен быть \\\
Также одинарные и двойные кавычки могут вызвать проблемы. Поэтому преобразование их в их эквивалент в юникоде является одним из способов избежать проблем. Более поздние версии PHP json_encode изменяют
'
на \u0027
и
"
на \u0022
Таким образом, применение этих трех правил к
O\'Rei\"lly
дает нам
O\\\u0027Rei\\\u0022lly
Эта строка затем обертывается в двойные кавычки, чтобы сделать ее строкой JSON. Ваши выражения replace включают ведущие прямые косые черты. Случайно или намеренно это означает, что ведущие и последующие двойные кавычки, возвращаемые json_encode
, не подвергаются экранированию, чего не должно быть.
Так в ранних версиях PHP
$s = addslashes('O\'Rei"lly');
print json_encode($s);
выводилось
"O\\'Rei\\\"lly"
и мы хотим изменить '
на \u0027
и мы хотим изменить \"
на \u0022
, потому что \
в \"
просто для того, чтобы вписать "
в строку, потому что она начинается и заканчивается двойными кавычками.
Поэтому мы получаем
"O\\\u0027Rei\\\u0022lly"
Поскольку вы собираетесь использовать json_encode
строку \ '
, вам нужно сначала закодировать \
, затем ] '
. Таким образом, у вас будут \\
и \ u0027
. Объединяя эти результаты \\ u0027
.
\
, сгенерированный addlashes ()
, повторно экранируется с помощью json_encode ()
. Вы, вероятно, хотели сказать это Выполнение json_encode ($ s, JSON_HEX_APOS | JSON_HEX_QUOT) выводит следующий
, но вы использовали $ str
вместо $ s
, что сбило с толку всех .
Если вы оцените строку "O \\ u0027Rei \\\ u0022lly"
в JavaScript, вы получите "O \ 'rei \" lly "
, и я довольно убедитесь, что это , а не то, что вам нужно. Когда вы оцените это, вам, вероятно, потребуется удалить все контрольные коды. Вперед, вставьте это в файл: alert ("O \\\ u0027Rei \\\ u0022lly ")
.
Заключение: вы дважды экранируете кавычки, что, скорее всего, не то, что вам нужно. json_encode
уже экранирует все, что необходимо, так что любой синтаксический анализатор JavaScript вернет исходный структура данных. В вашем случае это строка, которую вы получили после вызова с добавлением косой черты
.
Доказательство:
<?php $out = json_encode(array(10, "h'ello", addslashes("h'ello re-escaped"))); ?>
<script type="text/javascript">
var out = <?php echo $out; ?>;
alert(out[0]);
alert(out[1]);
alert(out[2]);
</script>
Это экранирование обратной косой черты, а также цитаты. Трудно иметь дело с побегами, как вы делаете здесь, так как это быстро превращается в игры со счетом с обратной косой чертой. : - /
Если я правильно понял, вы просто хотите знать, почему вам нужно использовать
'\\\\u0027'
, а не просто'\\\u0027'
Вы экранируете слэш и значение символа unicode. Этим вы говорите json, что он должен поставить здесь апостроф, но ему нужен обратный слеш и u, чтобы понять, что дальше идет шестнадцатеричный код символа.
Поскольку вы экранируете эту строку:
$s = addslashes('O\'Rei"lly'); // O\'Rei\"lly
первый обратный слеш на самом деле экранирует обратный слеш перед апострофом. Затем следующая косая черта используется для экранирования обратной косой черты, используемой json для идентификации символа как символа юникода.
Если бы вы применяли алгорифм к O'Reilly вместо O\'Rei\"lly, то достаточно было бы последнего.
Я надеюсь, что вы найдете это полезным. Я оставляю вам эту ссылку, чтобы вы могли прочитать больше о том, как строится json, поскольку очевидно, что вы уже понимаете PHP:
Когда вы кодируете строку для json, некоторые вещи необходимо экранировать независимо от параметров. Как отмечали другие, это включает '\', поэтому любая обратная косая черта, проходящая через json_encode, будет удвоена. Поскольку вы сначала запускаете свою строку через addlashes, которые также добавляют обратные косые черты к кавычкам, вы добавляете много дополнительных обратных косых черт. Следующая функция будет имитировать, как json_encode будет кодировать строку. Если к строке уже добавлены обратные косые черты, они будут удвоены.
function json_encode_string( $encode , $options ) {
$escape = '\\\0..\37';
$needle = array();
$replace = array();
if ( $options & JSON_HEX_APOS ) {
$needle[] = "'";
$replace[] = '\u0027';
} else {
$escape .= "'";
}
if ( $options & JSON_HEX_QUOT ) {
$needle[] = '"';
$replace[] = '\u0022';
} else {
$escape .= '"';
}
if ( $options & JSON_HEX_AMP ) {
$needle[] = '&';
$replace[] = '\u0026';
}
if ( $options & JSON_HEX_TAG ) {
$needle[] = '<';
$needle[] = '>';
$replace[] = '\u003C';
$replace[] = '\u003E';
}
$encode = addcslashes( $encode , $escape );
$encode = str_replace( $needle , $replace , $encode );
return $encode;
}