Perché la funzione PHP json_encode converte le stringhe UTF-8 in entità esadecimali?


148

Ho uno script PHP che si occupa di una grande varietà di lingue. Sfortunatamente, ogni volta che provo a usare json_encode, qualsiasi output Unicode viene convertito in entità esadecimali. È questo il comportamento previsto? C'è un modo per convertire l'output in caratteri UTF-8?

Ecco un esempio di quello che sto vedendo:

INGRESSO

echo $text;

PRODUZIONE

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

INGRESSO

json_encode($text);

PRODUZIONE

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

Risposte:


355

A partire da PHP / 5.4.0, esiste un'opzione chiamata "JSON_UNESCAPED_UNICODE" . Controlla:

http://se2.php.net/json_encode

Pertanto dovresti provare:

json_encode( $text, JSON_UNESCAPED_UNICODE );

3
Aha. Grazie! Avrei dovuto leggere la documentazione più attentamente. Grazie.
David Jones,

3
JSON_UNESCAPED_UNICODE è stato introdotto in PHP 5.4.0 e non è disponibile nelle versioni precedenti. Quando lo si utilizza nelle versioni precedenti si otterrà questo errore: "Attenzione: json_encode () prevede che il parametro 2 sia lungo, stringa indicata in ...". Vedere la risposta di CertaiN di seguito per la soluzione 5.3.
Ottaviano Naicu,

Questo funziona anche con lettere danesi Æ, æ, Ø, ø, Å, å Grazie!
Ymerdrengene,

Fantastico, questa era la risposta che stavo cercando!
randomizzatore,

2
Mi hai appena salvato la vita. GRAZIE.
Jon Zangitu,

57

JSON_UNESCAPED_UNICODE è disponibile su PHP versione 5.4 o successive.
Il codice seguente è per la versione 5.3.

AGGIORNATO

  • html_entity_decodeè un po 'più efficiente di pack+ mb_convert_encoding.
  • (*SKIP)(*FAIL)salta le barre rovesciate e i caratteri specificati dalle JSON_HEX_*bandiere.

 

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
Non dovresti essere maiuscolo?
Malhal,

4
Bella soluzione per PHP <5.4;)
qdev,

Stavo cercando 3 giorni per trovare questa soluzione per la versione 5.3 poiché il mio host non si è aggiornato alla 5.4. Per me sei un salvavita e per essere così completo preferirei contrassegnarlo come risposta accettata!
Laci,

Bug risolto quando la stringa contiene \\ . La versione più recente prende \\ una priorità più alta rispetto a \u.
mpyw,

Questo dovrebbe essere aggiunto nella libreria php. Buon lavoro.
Beraki,

7

Ti piace impostare charset e unicode senza escape

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

4

Una soluzione è prima codificare i dati e quindi decodificarli nello stesso file:

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

1

Ecco la mia soluzione combinata per varie versioni di PHP.

Nella mia azienda stiamo lavorando con diversi server con varie versioni di PHP, quindi ho dovuto trovare una soluzione che funzionasse per tutti.

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

I crediti dovrebbero andare a Marco Gasi & abu . La soluzione per PHP> = 5.4 è fornita nei documenti json_encode.


0

La funzione raw_json_encode () sopra non mi ha risolto il problema (per qualche motivo, la funzione di callback ha generato un errore sul mio server PHP 5.2.5).

Ma questa altra soluzione ha funzionato davvero.

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

I crediti dovrebbero andare a Marco Gasi . Ho appena chiamato la sua funzione invece di chiamare 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

Dal momento che hai chiesto:

C'è un modo per convertire l'output in caratteri UTF-8?

Un'altra soluzione è utilizzare utf8_encode .

Questo codificherà la stringa in UTF-8.

per esempio

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

echo json_encode($rows);

2
Non usare questo. Come indicato nella pagina del documento PHP, utf8_encode è appropriato solo se la stringa originale è codificata ISO-8859-1 (Latin1). Non è una funzione "assicurati che questa stringa sia codificata utf-8".
Telomere,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.