Tại sao hàm json_encode của PHP chuyển đổi các chuỗi UTF-8 thành các thực thể thập lục phân?


148

Tôi có một tập lệnh PHP liên quan đến nhiều ngôn ngữ. Thật không may, bất cứ khi nào tôi cố gắng sử dụng json_encode, mọi đầu ra Unicode đều được chuyển đổi thành các thực thể thập lục phân. Đây có phải là hành vi dự kiến? Có cách nào để chuyển đổi đầu ra thành các ký tự UTF-8 không?

Đây là một ví dụ về những gì tôi đang thấy:

ĐẦU VÀO

echo $text;

ĐẦU RA

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

ĐẦU VÀO

json_encode($text);

ĐẦU RA

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

Câu trả lời:


355

Kể từ PHP / 5.4.0, có một tùy chọn được gọi "JSON_UNESCAPED_UNICODE". Kiểm tra xem nó:

http://se2.php.net/json_encode

Vì vậy, bạn nên thử:

json_encode( $text, JSON_UNESCAPED_UNICODE );

3
Aha. Cảm ơn! Tôi nên đọc tài liệu cẩn thận hơn. Cảm ơn.
David Jones

3
JSON_UNESCAPED_UNICODE đã được giới thiệu trong PHP 5.4.0 và không có sẵn trong các phiên bản trước. Khi sử dụng nó trong các phiên bản trước, bạn sẽ gặp lỗi này: "Cảnh báo: json_encode () dự kiến ​​tham số 2 sẽ dài, chuỗi được đưa ra trong ...". Xem câu trả lời của CertaiN dưới đây cho giải pháp 5.3.
Octavian Naicu

Điều này cũng hoạt động với các chữ cái Đan Mạch,,, ø, Å, å Cảm ơn bạn!
ymerdrengene

Thật tuyệt vời, đây là câu trả lời tôi đang tìm kiếm!
ngẫu nhiên

2
Bạn vừa cứu mạng tôi. CẢM ƠN.
Jon Zangitu

57

JSON_UNESCAPED_UNICODE có sẵn trên phiên bản PHP 5.4 trở lên.
Đoạn mã sau dành cho Phiên bản 5.3.

CẬP NHẬT

  • html_entity_decodehiệu quả hơn một chút so với pack+ mb_convert_encoding.
  • (*SKIP)(*FAIL)bỏ qua dấu gạch chéo ngược chính nó và các ký tự được chỉ định bằng JSON_HEX_*cờ.

 

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
Không phải \ u là \ U tức là chữ hoa?
malhal

4
Giải pháp tuyệt vời cho PHP <5,4;)
qdev

Tôi đã tìm kiếm 3 ngày để tìm giải pháp này cho Phiên bản 5.3 vì máy chủ của tôi không nâng cấp lên 5.4. Đối với tôi bạn là một người tiết kiệm cuộc sống và vì đã hoàn thành nên tôi muốn đánh dấu đây là câu trả lời được chấp nhận!
Laci

Đã sửa lỗi khi chuỗi chứa \\ . Phiên bản mới lấy \\ ưu tiên cao hơn \u.
mpyw

Điều này nên được thêm vào trong thư viện php. Làm tốt lắm.
Beraki

7

Bạn thích đặt bộ ký tự và uniccted unicode

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

4

Một giải pháp là đầu tiên mã hóa dữ liệu và sau đó giải mã nó trong cùng một tệp:

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

1

Đây là giải pháp kết hợp của tôi cho các phiên bản PHP khác nhau.

Trong công ty của tôi, chúng tôi đang làm việc với các máy chủ khác nhau với các phiên bản PHP khác nhau, vì vậy tôi phải tìm giải pháp hoạt động cho tất cả.

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

Tín dụng nên đến Marco Gasi & abu . Giải pháp cho PHP> = 5.4 được cung cấp trong các tài liệu json_encode.


0

Hàm raw_json_encode () ở trên không giải quyết được vấn đề cho tôi (vì một số lý do, hàm gọi lại đã phát sinh lỗi trên máy chủ PHP 5.2.5 của tôi).

Nhưng giải pháp khác này đã thực sự làm việc.

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

Tín dụng nên đến Marco Gasi . Tôi chỉ gọi hàm của anh ấy thay vì gọi 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

Vì bạn đã hỏi:

Có cách nào để chuyển đổi đầu ra thành các ký tự UTF-8 không?

Một giải pháp khác là sử dụng utf8_encode .

Điều này sẽ mã hóa chuỗi của bạn đến UTF-8.

ví dụ

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

echo json_encode($rows);

2
Đừng dùng cái này. Như đã nêu trong trang tài liệu PHP, utf8_encode chỉ thích hợp nếu chuỗi gốc của bạn được mã hóa ISO-8859-1 (Latin1). Đây không phải là mục đích "đảm bảo chuỗi này được mã hóa utf-8".
telomere

-5

Đây có phải là hành vi dự kiến?

các json_encode()chỉ làm việc với dữ liệu UTF-8 mã hóa.

có lẽ bạn có thể nhận được câu trả lời để chuyển đổi nó ở đây: cyrillic-character-in-phps-json-encode

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.