Mengapa fungsi PHP json_encode mengubah string UTF-8 menjadi entitas heksadesimal?

148

Saya memiliki skrip PHP yang berhubungan dengan berbagai bahasa. Sayangnya, setiap kali saya mencoba menggunakan json_encode, setiap output Unicode dikonversi ke entitas heksadesimal. Apakah ini perilaku yang diharapkan? Apakah ada cara untuk mengubah output menjadi karakter UTF-8?

Berikut ini contoh dari apa yang saya lihat:

MEMASUKKAN

echo $text;

KELUARAN

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

MEMASUKKAN

json_encode($text);

KELUARAN

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

Jawaban:

355

Sejak PHP / 5.4.0, ada opsi yang disebut "JSON_UNESCAPED_UNICODE". Saksikan berikut ini:

http://se2.php.net/json_encode

Karena itu Anda harus mencoba:

json_encode( $text, JSON_UNESCAPED_UNICODE );
John Severinson
sumber
3
Aha. Terima kasih! Seharusnya saya membaca dokumentasinya dengan lebih cermat. Terima kasih.
David Jones
3
JSON_UNESCAPED_UNICODE diperkenalkan di PHP 5.4.0, dan tidak tersedia di versi sebelumnya. Saat menggunakannya di versi sebelumnya, Anda akan mendapatkan kesalahan ini: "Peringatan: json_encode () mengharapkan parameter 2 menjadi panjang, string yang diberikan dalam ...". Lihat jawaban CertaiN di bawah ini untuk solusi 5.3.
Oktavianus Naicu
Ini juga berfungsi dengan huruf-huruf Denmark Æ, æ, Ø, ø, Å, å Terima kasih!
ymerdrengene
Luar biasa, inilah jawaban yang saya cari!
Pengacak
2
Anda baru saja menyelamatkan hidup saya. TERIMA KASIH.
Jon Zangitu
57

JSON_UNESCAPED_UNICODE tersedia di PHP Versi 5.4 atau yang lebih baru.
Kode berikut untuk Versi 5.3.

DIPERBARUI

  • html_entity_decodesedikit lebih efisien daripada pack+ mb_convert_encoding.
  • (*SKIP)(*FAIL)melompati backslash itu sendiri dan karakter yang ditentukan oleh JSON_HEX_*bendera.

 

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));
}
mpyw
sumber
1
Bukankah seharusnya huruf besar adalah huruf besar?
Malhal
4
Solusi yang bagus untuk PHP <5.4;)
qdev
Saya mencari 3 hari untuk menemukan solusi ini untuk Versi 5.3 karena host saya tidak meningkatkan ke 5.4. Bagi saya, Anda adalah penyelamat hidup dan karena begitu lengkap saya lebih suka menandai ini sebagai jawaban yang diterima!
Laci
Memperbaiki bug saat string berisi \\ . Versi \\ yang lebih baru lebih diprioritaskan daripada \u.
mpyw
Ini harus ditambahkan di perpustakaan php. Kerja bagus.
Beraki
7

Anda suka mengatur charset dan unescaped unicode

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

Salah satu solusinya adalah dengan terlebih dahulu menyandikan data dan mendekode dalam file yang sama:

$string =json_encode($input, JSON_UNESCAPED_UNICODE) ; 
echo $decoded = html_entity_decode( $string );
Steffo Dimfelt
sumber
1

Ini adalah solusi gabungan saya untuk berbagai versi PHP.

Di perusahaan saya, kami bekerja dengan server yang berbeda dengan berbagai versi PHP, jadi saya harus mencari solusi yang berfungsi untuk semua.

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

Kredit harus diberikan kepada Marco Gasi & abu . Solusi untuk PHP> = 5.4 disediakan dalam json_encode docs.

gaba
sumber
0

Fungsi raw_json_encode () di atas tidak menyelesaikan masalah saya (karena beberapa alasan, fungsi panggilan balik menimbulkan kesalahan pada server PHP 5.2.5 saya).

Tetapi solusi lain ini benar-benar berhasil.

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

Kredit harus diberikan kepada Marco Gasi . Saya hanya memanggil fungsinya alih-alih memanggil 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 ) );
}
abu
sumber
0
json_encode($text, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
Ho Vng Tgtt
sumber
-2

Karena Anda bertanya:

Apakah ada cara untuk mengubah output menjadi karakter UTF-8?

Solusi lain adalah dengan menggunakan utf8_encode .

Ini akan menyandikan string Anda ke UTF-8.

misalnya

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

echo json_encode($rows);
Robin Carlo Catacutan
sumber
2
Jangan gunakan ini. Seperti yang dinyatakan dalam halaman doc PHP, utf8_encode hanya sesuai jika string asli Anda adalah ISO-8859-1 (Latin1) yang dikodekan. Ini bukan tujuan semua "pastikan string ini utf-8 dikodekan" fungsi.
telomer
-5

Apakah ini perilaku yang diharapkan?

json_encode()satu - satunya yang berfungsi dengan data yang dikodekan UTF-8.

mungkin Anda bisa mendapatkan jawaban untuk mengubahnya di sini: cyrillic-karakter-in-phps-json-encode

JoakimH
sumber