web-dev-qa-db-fra.com

json_encode () non utf-8 strings?

Donc, j'ai un tableau de chaînes, et toutes les chaînes utilisent le codage ANSI par défaut du système et ont été extraites d'une base de données SQL. Il y a donc 256 valeurs d'octet de caractère différentes possibles (codage sur un octet). Existe-t-il un moyen de faire en sorte que json_encode () fonctionne et affiche ces caractères au lieu d’utiliser utf8_encode () sur toutes mes chaînes et d’obtenir des éléments tels que "\ u0082"? 

Ou est-ce la norme pour JSON? 

23
Josh

Existe-t-il un moyen de faire en sorte que json_encode () fonctionne et affiche ces caractères au lieu de devoir utiliser utf8_encode () sur toutes mes chaînes et de se retrouver avec des éléments tels que "\ u0082"?

Si vous avez une chaîne encodée en ANSI, utiliser utf8_encode() est la fonction Incorrect pour résoudre ce problème. Vous devez d’abord convertir correctement le format ANSI en UTF-8. Cela réduira certainement le nombre de séquences d'échappement Unicode telles que \u0082 depuis la sortie json, mais techniquement, ces séquences sont valables pour json , vous ne devez pas les craindre.

Conversion ANSI en UTF-8 avec PHP

json_encode fonctionne avec les chaînes codées UTF-8uniquement. Si vous devez créer une variable json valide à partir d'une chaîne codée ANSI, vous devez d'abord la recoder/la convertir en UTF-8. Ensuite, json_encode fonctionnera comme indiqué.

Pour convertir un encodage de ANSI (plus correctement, je suppose que vous avez une chaîne encodée Windows-1252, qui est populaire mais appelée à tort ANSI) en UTF-8, vous pouvez utiliser la fonction mb_convert_encoding() :

$str = mb_convert_encoding($str, "UTF-8", "Windows-1252");

Une autre fonction de PHP capable de convertir le codage/jeu de caractères d'une chaîne est appelée iconv sur la base de libiconv . Vous pouvez aussi l'utiliser:

$str = iconv("CP1252", "UTF-8", $str);

Note sur utf8_encode ()

utf8_encode() ne fonctionne que pour Latin-1 et non pour ANSI. Donc, vous allez détruire une partie de vos personnages à l'intérieur de cette chaîne lorsque vous l'exécutez à travers cette fonction.


Connexes: Qu'est-ce que le format ANSI?


Pour un contrôle plus précis de ce que json_encode() renvoie, consultez la liste des constantes prédéfinies } (fonction de la version de PHP, y compris PHP 5.4, certaines constantes restent non documentées et ne sont disponibles que dans le code source. jusque là).

Changer l'encodage d'un tableau/de manière itérative (commentaire PDO)

Comme vous avez écrit dans un commentaire que vous avez des problèmes pour appliquer la fonction à un tableau, voici un exemple de code. C'est toujours nécessaire pour premier changer l'encodage avant d'utiliser json_encode. Ceci est juste une opération de tableau standard, pour le cas plus simple de pdo::fetch() une itération foreach:

while($row = $q->fetch(PDO::FETCH_ASSOC))
{
  foreach($row as &$value)
  {
    $value = mb_convert_encoding($value, "UTF-8", "Windows-1252");
  }
  unset($value); # safety: remove reference
  $items[] = array_map('utf8_encode', $row );
}
32
hakre

La norme JSON ENFORCES Le codage Unicode. De RFC4627 :

3.  Encoding

   JSON text SHALL be encoded in Unicode.  The default encoding is
   UTF-8.

   Since the first two characters of a JSON text will always be ASCII
   characters [RFC0020], it is possible to determine whether an octet
   stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
   at the pattern of nulls in the first four octets.

           00 00 00 xx  UTF-32BE
           00 xx 00 xx  UTF-16BE
           xx 00 00 00  UTF-32LE
           xx 00 xx 00  UTF-16LE
           xx xx xx xx  UTF-8

Par conséquent, au sens strict, JSON codé en ANSI ne serait pas un JSON valide; C'est pourquoi PHP applique le codage Unicode lors de l'utilisation de json_encode() .

En ce qui concerne "ANSI par défaut", je suis à peu près sûr que vos chaînes sont codées dans Windows-1252. Il est appelé à tort ANSI.

8
Andrew Moore
<?php
$array = array('first Word' => array('Слово','Кириллица'),'second Word' => 'Кириллица','last Word' => 'Кириллица');
echo json_encode($array);
/*
return {"first Word":["\u0421\u043b\u043e\u0432\u043e","\u041a\u0438\u0440\u0438\u043b\u043b\u0438\u0446\u0430"],"second Word":"\u041a\u0438\u0440\u0438\u043b\u043b\u0438\u0446\u0430","last Word":"\u041a\u0438\u0440\u0438\u043b\u043b\u0438\u0446\u0430"}
*/
echo json_encode($array,256);
/*
return {"first Word":["Слово","Кириллица"],"second Word":"Кириллица","last Word":"Кириллица"}
*/
?>

JSON_UNESCAPED_UNICODE (entier) Encodez littéralement des caractères Unicode multi-octets (le comportement par défaut est d'échapper à\uXXXX). Disponible depuis PHP 5.4.0.

http://php.net/manual/en/json.constants.php#constant.json-unescaped-unicode

4
Jenyok

Oui, ceci est un comportement standard pour JSON sous PHP

Si vous lisez la documentation: http://php.net/manual/en/function.json-encode.php
Vous verrez que cela ne peut fonctionner qu'avec les données encodées en utf-8,

d'autre part, vous pouvez utiliser le premier commentaire dans: http://php.net/manual/en/function.json-encode.php#104278

et créez votre propre fonction d'encodage/décodage en utilisant ANSI

1
Marek Sebera

Pour imprimer le mot espagnol, j'ai finalement obtenu la solution comme ci-dessous avec l'application de deux fonctions.

$conn->set_charset("utf8");

mb_convert_encoding('THE BULLOCK ÉTAGÈRE - 3 SHELVES', "UTF-8", "Windows-1252")

Où 'THE BULLOCK É TAGÈRE - 3 ÉTAGÈRES' cette chaîne provient d'une base de données. J'ai donc d'abord l'objet de base de données conn pour définir le caractère comme utf8 puis j'ai encodé le mot espagnol UTF-8 to Windows-1252

0
Bhavin Thummar