Почему json_decode конвертирует мою строку в юникоде? - PullRequest
0 голосов
/ 03 июля 2019

У меня есть строка с символами Unicode.

Например:

$s = '"x9gtjw\u001d91ffd0\u001d92K"';
var_dump($s, json_decode($s));

Это дает вывод:

string '"x9gtjw\u001d91ffd0\u001d92K"' (length=29)
string 'x9gtjw91ffd092K' (length=17)

Почему json_decode преобразует мои символы Unicode?

Я использую PHP 7.2.

Я пытался использовать флаги (например, JSON_INVALID_UTF8_SUBSTITUTE), но они не помогли.

Обновление:

Мне нужно использовать json_decode без преобразования \uXXXX вгекс \xXX.

Например:

$s = '{"code":"zz\u001d"}';
$json = json_decode($s);
if($json->code == 'zz\u001d') {...}

Строка $s содержит невидимые символы \x1d.

Я попытался преобразовать обратные косые черты в двойные обратные косые черты - что не повлияло на вывод.

Ответы [ 2 ]

1 голос
/ 04 июля 2019

Ваши строки $s (обе!) Не содержат никаких "невидимых символов \ x1d" (разделитель групп (GS) согласно ASCII).Они оба содержат буквальную обратную косую черту, за которой следует буква «u» и т. Д.

Теперь, что еще не так там: если вы напечатаете строку 'a\x0ab', вы получите ее в том виде, в каком она здесь стоит, минусцитаты.Если вы напечатаете строку "a\x0ax", вы получите «a» и «b», разделенные переводом строки.Строковые литералы с одинарными кавычками ведут себя по-другому, чем строковые литералы в PHP.

Теперь вам может быть интересно, как избежать json_decode () от интерпретации последовательности \uxxxx.Простой ответ: вы не можете, потому что это противоречит спецификации JSON, и ни один здравомыслящий парсер не сделает этого.То, что вы можете сделать, это в основном две вещи:

  1. Исправить ввод, чтобы он содержал обратную косую черту, которая не является частью escape-последовательности.Это означает, что вы должны удвоить обратную косую черту во входной строке.Поскольку в PHP обратная косая черта также интерпретируется как escape-символ, вам придется увеличить ее в четыре раза.Вы можете видеть, что если вы закодируете ожидаемый результат, используя json_encode().
  2. Исправьте все, что вы хотите сделать с выводом.Спросите себя, почему вы хотите что-то в выходной строке, которое не предназначено для представления в JSON, например управляющие символы, которые явно исключены.Если это просто из-за того, что вы не можете отобразить его, или потому что это портит какое-то форматирование, убедитесь, что при выводе его все работает, но не меняйте внутреннее представление на что-то нелогичное.
1 голос
/ 04 июля 2019

Символы все еще существуют в декодированной строке string 'x9gtjw91ffd092K' (length=17), но они не отображаются. 1D - управляющий код ASCII для разделителя групп (непечатный символ).

Обратите внимание, что размер длины строки в два раза больше (17), чем отображаемая строка (15), поскольку символ UTF-8 равен \x1d и в строке два символа.

Если бы символ был: \u0A1 (Upsidedown Exclamation Point), версия UTF-8 добавила бы 2 дополнительных байта (\xc2\xa1). Это может существовать до 4 дополнительных байтов (более высокий эмодзи UTF-32).

Ваше сравнение не работает, потому что:

Вы должны удвоить двойную обратную косую черту \\\\, чтобы избежать кодировки Unicode.

$s = '{"code":"zz\\\\u001d"}';
$json = json_decode($s);
if($json->code == 'zz\u001d') {...}

в противном случае \u001d будет интерпретироваться при декодировании.

Здесь объясняется более естественный способ сделать это (не то, что спрашивали, но все же как решение):

PHP требует двойных кавычек ", когда он содержит escape-последовательности \uXXXX. Ссылка (раздел" Двойные кавычки ", 1 страница вниз) .

Просто измените свой код обнаружения, следуя этому требованию:

$s = '{"code":"zz\u001d"}';
$json = json_decode($s);
if($json->code == "zz\u001d") {...}

Код, указанный в {...}, теперь будет работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...