Pourquoi la fonction PHP json_encode convertit-elle les chaînes UTF-8 en entités hexadécimales?


148

J'ai un script PHP qui traite une grande variété de langages. Malheureusement, chaque fois que j'essaie d'utiliser json_encode, toute sortie Unicode est convertie en entités hexadécimales. Est-ce le comportement attendu? Existe-t-il un moyen de convertir la sortie en caractères UTF-8?

Voici un exemple de ce que je vois:

CONTRIBUTION

echo $text;

PRODUCTION

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

CONTRIBUTION

json_encode($text);

PRODUCTION

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

Réponses:


355

Depuis PHP / 5.4.0, il existe une option appelée "JSON_UNESCAPED_UNICODE". Vérifiez-le:

http://se2.php.net/json_encode

Par conséquent, vous devriez essayer:

json_encode( $text, JSON_UNESCAPED_UNICODE );

3
Aha. Merci! J'aurais dû lire la documentation plus attentivement. Merci.
David Jones

3
JSON_UNESCAPED_UNICODE a été introduit dans PHP 5.4.0 et n'est pas disponible dans les versions antérieures. Lorsque vous l'utilisez dans des versions antérieures, vous obtiendrez cette erreur: "Attention: json_encode () s'attend à ce que le paramètre 2 soit long, chaîne donnée dans ...". Voir la réponse de CertaiN ci-dessous pour la solution 5.3.
Octavian Naicu

Cela fonctionne également avec les lettres danoises Æ, æ, Ø, ø, Å, å Merci!
ymerdrengene

Fantastique, c'était la réponse que je cherchais!
randomizer

2
Tu viens de me sauver la vie. MERCI.
Jon Zangitu

57

JSON_UNESCAPED_UNICODE est disponible sur PHP version 5.4 ou ultérieure.
Le code suivant est pour la version 5.3.

ACTUALISÉ

  • html_entity_decodeest un peu plus efficace que pack+ mb_convert_encoding.
  • (*SKIP)(*FAIL)saute les barres obliques inverses et les caractères spécifiés par des JSON_HEX_*indicateurs.

 

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
Le \ u ne devrait-il pas être \ U c'est-à-dire majuscule?
malhal

4
Belle solution pour PHP <5.4;)
qdev

Je cherchais 3 jours pour trouver cette solution pour la version 5.3 car mon hôte n'a pas mis à niveau vers la version 5.4. Pour moi, vous êtes un sauveur de vie et pour être si complet, je préfère marquer cela comme une réponse acceptée!
Laci

Correction d'un bug lorsque la chaîne contient \\ . La nouvelle version obtient \\ une priorité plus élevée que \u.
mpyw

Cela devrait être ajouté dans la bibliothèque php. Bon travail.
Beraki

7

Vous aimez définir un jeu de caractères et unicode sans échappement

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

4

Une solution consiste à encoder d'abord les données, puis à les décoder dans le même fichier:

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

1

Voici ma solution combinée pour différentes versions de PHP.

Dans mon entreprise, nous travaillons avec différents serveurs avec différentes versions de PHP, j'ai donc dû trouver une solution qui fonctionne pour tous.

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

Les crédits doivent aller à Marco Gasi & abu . La solution pour PHP> = 5.4 est fournie dans la documentation json_encode.


0

La fonction raw_json_encode () ci - dessus ne m'a pas résolu le problème (pour une raison quelconque, la fonction de rappel a soulevé une erreur sur mon serveur PHP 5.2.5).

Mais cette autre solution a fonctionné.

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

Les crédits devraient aller à Marco Gasi . J'appelle juste sa fonction au lieu d'appeler 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

Depuis que vous avez demandé:

Existe-t-il un moyen de convertir la sortie en caractères UTF-8?

Une autre solution consiste à utiliser utf8_encode .

Cela encodera votre chaîne en UTF-8.

par exemple

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

echo json_encode($rows);

2
N'utilisez pas ça. Comme indiqué dans la page de documentation PHP, utf8_encode n'est approprié que si votre chaîne d'origine est encodée ISO-8859-1 (Latin1). Ce n'est pas une fonction polyvalente "assurez-vous que cette chaîne est encodée en utf-8".
telomere

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.