web-dev-qa-db-fra.com

PHP décodage et encodage json avec des caractères unicode

J'ai un json dont j'ai besoin pour décoder, modifier puis encoder sans gâcher aucun caractère.

Si j'ai un caractère unicode dans une chaîne json, il ne sera pas décodé. Je ne sais pas pourquoi puisque json.org dit qu'une chaîne peut contenir: any-Unicode-character- except-"-or-\-or- control-character. Mais cela ne fonctionne pas non plus en python.

{"Tag":"Odómetro"}

Je peux utiliser utf8_encode qui permettra à la chaîne d'être décodée avec json_decode, mais le personnage est mutilé dans autre chose. C'est le résultat d'un print_r du tableau de résultats. Deux personnages.

[Tag] => Odómetro

Lorsque j'encode à nouveau le tableau, le caractère s'est échappé vers ascii, ce qui est correct selon la spécification json:

"Tag"=>"Od\u00f3metro"

Y a-t-il un moyen de ne pas y échapper? json_encode ne donne pas une telle option, utf8_encode ne semble pas fonctionner non plus.

Edit Je vois qu'il y a une option unescaped_unicode pour json_encode. Cependant, cela ne fonctionne pas comme prévu. Oh putain, c'est seulement sur php 5.4. Je vais devoir utiliser des regex car je n'en ai que 5.3.

$json = json_encode($array, JSON_UNESCAPED_UNICODE);
Warning: json_encode() expects parameter 2 to be long, string ...
33
Keyo

À en juger par tout ce que vous avez dit, il semble que l'original Odómetro la chaîne que vous traitez est encodée avec ISO 8859-1, pas UTF-8.

Voici pourquoi je pense que oui:

  • json_encode a produit une sortie analysable après avoir exécuté la chaîne d'entrée via utf8_encode, qui passe de ISO 8859-1 à UTF-8.
  • Vous avez dit que vous aviez obtenu une sortie "mutilée" lors de l'utilisation de print_r après avoir fait utf8_encode, mais la sortie altérée que vous avez obtenue est exactement ce qui se passerait en essayant d'analyser le texte UTF-8 en ISO 8859-1 (ó est \x63\xb3 en UTF-8, mais cette séquence est ó dans ISO 8859-1.
  • Votre solution de piratage htmlentities a fonctionné. htmlentities a besoin de savoir quel est l'encodage de la chaîne d'entrée pour fonctionner correctement. Si vous n'en spécifiez pas, cela suppose ISO 8859-1. (html_entity_decode, confusément, par défaut en UTF-8, donc votre méthode a eu pour effet de convertir ISO 8859-1 en UTF-8.)
  • Vous avez dit que vous aviez le même problème en Python, ce qui semble exclure PHP d'être le problème.

PHP utilisera le \uXXXX s'échappant, mais comme vous l'avez noté, c'est du JSON valide.

Il semble donc que vous deviez configurer votre connexion à Postgres afin qu'il vous donne des chaînes UTF-8. Le manuel PHP indique que vous feriez cela en ajoutant options='--client_encoding=UTF8' à la chaîne de connexion. Il est également possible que les données actuellement stockées dans la base de données soient mal encodées. (Vous pouvez simplement utiliser utf8_encode, mais cela ne prendra en charge que les caractères faisant partie de l'ISO 8859-1).

Enfin, comme une autre réponse l'a noté, vous devez vous assurer que vous déclarez le jeu de caractères approprié, avec un en-tête HTTP ou autre (bien sûr, ce problème particulier pourrait simplement être un artefact de l'environnement dans lequel vous avez fait votre print_r tests).

14
John Flatness

J'ai trouvé le moyen suivant pour résoudre ce problème ... J'espère que cela peut vous aider.

json_encode($data,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
31
Sunny S.M

JSON_UNESCAPED_UNICODE a été ajouté dans PHP 5.4, il semble donc que vous ayez besoin de mettre à niveau votre version de PHP pour en profiter. 5.4 n'est pas encore publié) bien que! :(

Il y a un 5.4 version alpha candidate sur QA si vous voulez jouer sur votre machine de développement.

16
Treffynnon

Une manière hacky de faire JSON_UNESCAPED_UNICODE en PHP 5.3. Vraiment déçu par PHP support json. Peut-être que cela aidera quelqu'un d'autre.

$array = some_json();
// Encode all string children in the array to html entities.
array_walk_recursive($array, function(&$item, $key) {
    if(is_string($item)) {
        $item = htmlentities($item);
    }
});
$json = json_encode($array);

// Decode the html entities and end up with unicode again.
$json = html_entity_decode($rson);
7
Keyo

essayez de définir le utf-8 encodage dans votre page:

header('content-type:text/html;charset=utf-8');

cela fonctionne pour moi:

$arr = array('tag' => 'Odómetro');
$encoded = json_encode($arr);
$decoded = json_decode($encoded);
echo $decoded->{'tag'};
4
The Mask
$json = array('tag' => 'Odómetro'); // Original array
$json = json_encode($json); // {"Tag":"Od\u00f3metro"}
$json = json_decode($json); // Od\u00f3metro becomes  Odómetro
echo $json->{'tag'}; // Odómetro
echo utf8_decode($json->{'tag'}); // Odómetro

Vous étiez proche, utilisez simplement utf8_decode.

4
Fernando R.

Essayez d'utiliser:

utf8_decode() and utf8_encode
3
Jonathan Edgardo

Pour coder un tableau contenant des caractères spéciaux, ISO 8859-1 à UTF8. (Si utf8_encode & utf8_decode ne fonctionne pas pour vous, cela pourrait être une option)

Tout ce qui est dans ISO-8859-1 devrait être converti en UTF8:

$utf8 = utf8_encode('이 감사의 마음을 전합니다!'); //contains UTF8 & ISO 8859-1 characters;    
$iso88591 = mb_convert_encoding($utf8, 'ISO-8859-1', 'UTF-8');
$data = $iso88591;

L'encodage devrait fonctionner après ceci:

$encoded_data = json_encode($data);

Convertir UTF-8 vers et depuis ISO 8859-1

0
Navaneeth Mohan