Чому функція PHP json_encode перетворює рядки UTF-8 у шістнадцяткові сутності?


148

У мене є сценарій PHP, який стосується найрізноманітніших мов. На жаль, кожен раз, коли я намагаюся використовувати json_encode, будь-який вихід Unicode перетворюється на шістнадцяткові сутності. Це очікувана поведінка? Чи є якийсь спосіб перетворити висновок на символи UTF-8?

Ось приклад того, що я бачу:

ВХОД

echo $text;

ВИХІД

База данни грешка.

ВХОД

json_encode($text);

ВИХІД

"\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u0438 \u0433\u0440\u0435\u0448\u043a\u0430."

Відповіді:


355

Оскільки PHP / 5.4.0, є опція, що називається "JSON_UNESCAPED_UNICODE". Перевір:

http://se2.php.net/json_encode

Тому слід спробувати:

json_encode( $text, JSON_UNESCAPED_UNICODE );

3
Ага. Дякую! Я повинен був уважніше прочитати документацію. Дякую.
Девід Джонс

3
JSON_UNESCAPED_UNICODE був представлений у PHP 5.4.0 і недоступний у попередніх версіях. Використовуючи його в попередніх версіях, ви отримаєте цю помилку: "Попередження: json_encode () очікує, що параметр 2 буде довгим, рядок задано в ...". Дивіться відповідь CertaiN нижче щодо рішення 5.3.
Октавіан Найку

Це також працює з датськими літерами Æ, æ, Ø, ø, Å, å Дякую!
ymerdrengene

Фантастично, це була відповідь, яку я шукав!
рандомизатор

2
Ти щойно врятував мені життя. ДЯКУЮ.
Джон Зангіту

57

JSON_UNESCAPED_UNICODE доступний у PHP версії 5.4 або новішої версії.
Наступний код призначений для версії 5.3.

ОНОВЛЕНО

  • html_entity_decodeтрохи ефективніше, ніж pack+ mb_convert_encoding.
  • (*SKIP)(*FAIL)пропускає нахил накиду і задає символи JSON_HEX_*прапорами.

 

function raw_json_encode($input, $flags = 0) {
    $fails = implode('|', array_filter(array(
        '\\\\',
        $flags & JSON_HEX_TAG ? 'u003[CE]' : '',
        $flags & JSON_HEX_AMP ? 'u0026' : '',
        $flags & JSON_HEX_APOS ? 'u0027' : '',
        $flags & JSON_HEX_QUOT ? 'u0022' : '',
    )));
    $pattern = "/\\\\(?:(?:$fails)(*SKIP)(*FAIL)|u([0-9a-fA-F]{4}))/";
    $callback = function ($m) {
        return html_entity_decode("&#x$m[1];", ENT_QUOTES, 'UTF-8');
    };
    return preg_replace_callback($pattern, $callback, json_encode($input, $flags));
}

1
Чи не слід \ u бути \ U, тобто великими літерами?
маль

4
Приємне рішення для PHP <5.4;)
qdev

Я шукав 3 дні, щоб знайти це рішення для версії 5.3, оскільки мій хост не оновив до 5.4. Мені ви є рятувальником життя, і для того, щоб бути настільки повною, я б скоріше відзначив це прийнятою відповіддю!
Лаці

Виправлена ​​помилка, коли рядок містить \\ . Новіша версія захоплює \\ більш високий пріоритет, ніж \u.
mpyw

Це слід додати в бібліотеку php. Хороша робота.
Беракі

7

Вам подобається встановлювати шаблони та нескаканізований унікод

 header('Content-Type: application/json;charset=utf-8');  
 json_encode($data,JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);

4

Одне рішення - спочатку кодувати дані, а потім розшифровувати їх у тому ж файлі:

$string =json_encode($input, JSON_UNESCAPED_UNICODE) ; 
echo $decoded = html_entity_decode( $string );

1

Ось моє комбіноване рішення для різних версій PHP.

У моїй компанії ми працюємо з різними серверами з різними версіями PHP, тому мені довелося знайти рішення, яке працює для всіх.

$phpVersion = substr(phpversion(), 0, 3)*1;

if($phpVersion >= 5.4) {
  $encodedValue = json_encode($value, JSON_UNESCAPED_UNICODE);
} else {
  $encodedValue = preg_replace('/\\\\u([a-f0-9]{4})/e', "iconv('UCS-4LE','UTF-8',pack('V', hexdec('U$1')))", json_encode($value));
}

Кредити мають бути передані Marco Gasi & abu . Рішення для PHP> = 5.4 надається в документах json_encode.


0

Наведена вище функція raw_json_encode () не вирішила мені проблеми (чомусь функція зворотного дзвінка викликала помилку на моєму сервері PHP 5.2.5).

Але це інше рішення насправді спрацювало.

https://www.experts-exchange.com/questions/28628085/json-encode-fails-with-special-characters.html

Кредити повинні надійти до Марко Гасі . Я просто називаю його функцію, а не дзвоню json_encode ():

function jsonRemoveUnicodeSequences( $json_struct )
{ 
    return preg_replace( "/\\\\u([a-f0-9]{4})/e", "iconv('UCS-4LE','UTF-8',pack('V', hexdec('U$1')))", json_encode( $json_struct ) );
}


-2

Оскільки ви запитали:

Чи є якийсь спосіб перетворити висновок на символи UTF-8?

Іншим рішенням є використання utf8_encode .

Це буде кодувати вашу рядок до UTF-8.

напр

foreach ($rows as $key => $row) {
  $rows[$key]["keyword"] = utf8_encode($row["keyword"]);
}

echo json_encode($rows);

2
Не використовуйте це. Як зазначено на сторінці документа PHP, utf8_encode підходить лише в тому випадку, якщо ваша початкова рядок зашифрована ISO-8859-1 (Latin1). Це не зовсім мета "переконайтеся, що ця рядок закодована utf-8".
теломер

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.