7 votes

Comment décoder une chaîne json en UTF-8 ?

Je travaille avec json depuis un certain temps et le problème est que les chaînes que je décode sont codées en Latin-1 et je ne peux pas les faire fonctionner en UTF-8. De ce fait, certains caractères sont affichés de manière incorrecte (par exemple, ' affiché comme ').

J'ai lu quelques questions ici sur stackoverflow, mais elles ne semblent pas fonctionner.

La structure json avec laquelle je travaille ressemble à ceci (elle provient de l'API de YouTube) :

...
"items": [
  {
   ...
   "snippet": {
    ...
    "title": "Powerbeats Pro “Totally Wireless” Except when you need a wire",
    ...
    }
   }
  ]

Je l'encode avec :

response = await http.get(link, headers: {HttpHeaders.contentTypeHeader: "application/json; charset=utf-8"});
extractedData = json.decode(response.body);
dataTech = extractedData["items"];

Et puis ce que j'ai essayé, c'est de changer la deuxième ligne en :

extractedData = json.decode(utf8.decode(response.body));

Mais cela m'a donné une erreur à cause d'un mauvais format. Alors je l'ai changé en :

extractedData = json.decode(utf8.decode(response.bodyBytes));

Cela n'entraîne pas l'erreur, mais ne résout pas non plus le problème. Jouer avec les en-têtes n'apporte rien.

Je voudrais que les données soient stockées dans dataTech comme elles le sont actuellement, mais codées en UTF-8. Qu'est-ce que je fais de mal ?

16voto

Richard Heap Points 15826

Juste un aparté d'abord : UTF-8 est typiquement un externe et généralement représenté par un tableau d'octets. C'est ce que vous pouvez envoyer sur le réseau dans le cadre d'une réponse HTTP. En interne, Dart stocke les chaînes de caractères sous forme de points de code UTF-16. Le site utf8 L'encodeur/décodeur convertit les chaînes de format interne en tableaux d'octets de format externe.

C'est pourquoi vous utilisez utf8.decode(response.bodyBytes) ; prendre les octets bruts du corps et les convertir en une chaîne interne. ( response.body fait aussi cela, mais il choisit le décodeur bytes->string en fonction du jeu de caractères de l'en-tête de la réponse. Lorsque cet en-tête est manquant (ce qui est souvent le cas), le décodeur http choisit Latin-1, ce qui ne fonctionne évidemment pas si vous savez que la réponse est dans un jeu de caractères différent). En utilisant utf8.decode vous-même, vous annulez le choix (potentiellement erroné) qui est fait par http parce que vous savez que ce serveur particulier envoie toujours UTF-8. (Il se peut que ce ne soit pas le cas, bien sûr !)

Autre parenthèse : la mise en place d'un en-tête de type de contenu sur un fichier de type demande est rarement utile. En général, vous n'envoyez pas de contenu - il n'a donc pas de type ! Et cela n'a aucune influence sur le type de contenu ou le jeu de caractères du type de contenu que le serveur vous renverra. Le site accept L'en-tête pourrait être ce que vous recherchez. Il s'agit d'un indice pour le serveur sur le type de contenu que vous souhaitez récupérer, mais tous les serveurs ne le respectent pas.

Alors pourquoi vos caractères spéciaux sont-ils toujours incorrects ? Essayez d'imprimer utf8.decode(response.bodyBytes) avant de le décoder. Est-ce que ça a l'air correct dans la console ? (Il est très utile de créer une simple application Dart en ligne de commande pour ce type de problème ; je trouve plus facile de définir des points d'arrêt et d'inspecter les variables dans une simple application Dart de dix lignes). Essayez d'utiliser quelque chose comme Wireshark pour capturer les octets sur le fil (encore une fois, il est utile d'avoir une application Dart simple pour cela). Ou essayez d'utiliser Postman pour envoyer la même requête et inspecter la réponse.

Comment essayez-vous de montrer les personnages. Il se peut simplement que la police que vous utilisez ne les ait pas.

7voto

Yasser Benmman Points 11

Ajoutez simplement l'en-tête : 'Accept' : 'application/json ; charset=UTF-8' ; cela a fonctionné pour moi

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X