2010-05-05 2 views
4

J'ai le mot suivant que je récupère via un service web: AndréComment stocker des caractères accentués provenant d'un service Web dans une base de données?

De Python, la valeur ressemble à: "Andr \ u00c3 \ u00a9". L'entrée est ensuite décodé à l'aide json.loads:

>>> import json 
>>> json.loads('{"name":"Andr\\u00c3\\u00a9"}') 
>>> {u'name': u'Andr\xc3\xa9'} 

Lorsque je stocke ci-dessus dans une base de données MySQL UTF8, les données sont stockées comme les suivantes en utilisant Django:

SomeObject.objects.create(name=u'Andr\xc3\xa9') 

Interrogation la colonne de nom d'un mysql coquille ou l'afficher dans une page Web donne: André

la page Web affiche en UTF8:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 

Ma base de données est configuré en UTF8:

mysql> SHOW VARIABLES LIKE 'collation%'; 
+----------------------+-----------------+ 
| Variable_name  | Value   | 
+----------------------+-----------------+ 
| collation_connection | utf8_general_ci | 
| collation_database | utf8_unicode_ci | 
| collation_server  | utf8_unicode_ci | 
+----------------------+-----------------+ 
3 rows in set (0.00 sec) 

mysql> SHOW VARIABLES LIKE 'character_set%'; 
+--------------------------+----------------------------+ 
| Variable_name   | Value      | 
+--------------------------+----------------------------+ 
| character_set_client  | utf8      | 
| character_set_connection | utf8      | 
| character_set_database | utf8      | 
| character_set_filesystem | binary      | 
| character_set_results | utf8      | 
| character_set_server  | utf8      | 
| character_set_system  | utf8      | 
| character_sets_dir  | /usr/share/mysql/charsets/ | 
+--------------------------+----------------------------+ 
8 rows in set (0.00 sec) 

Comment puis-je récupérer le mot André à partir d'un service Web, stocker correctement dans une base de données sans perte de données et les afficher sur une page Web dans sa version originale forme?

+2

Jusqu'à présent, je ne vois aucun problème ici. Ce que vous voyez de Python est la représentation Unicode de votre chaîne "André". Chaque caractère est stocké dans deux octets. Lorsque vous le stockez dans MySQL, le moteur de base de données le convertit automatiquement en encodage UTF-8 à la volée. En UTF-8, certains caractères sont stockés en utilisant 1 octet seulement, tandis que d'autres utilisent plusieurs octets, mais il n'y a pas de perte de données ici, la chaîne d'origine peut être obtenue à tout moment depuis la représentation codée en UTF-8. –

+0

Bien qu'ils ne soient pas 100% identiques à votre pile technologique, jetez un coup d'oeil à http://stackoverflow.com/questions/279170/utf-8-all-the-way-through pour une bonne explication de la manipulation de l'utf-8 sans perte grâce à tous les niveaux. – ataylor

+0

@Tamas: FAUX; regardez 'u'Andr \ xc3 \ xa9''; l'e-acute prend quatre octets; voir @ réponse de Bernd –

Répondre

6

La faute est déjà dans la chaîne que vous transmettez à json.loads(). \ u00c3 est "A tilde" et \ 00a9 est le signe du copyright. Correct pour é serait \ u00e9.

Probablement la chaîne a été codée en UTF-8 par l'expéditeur et décodée comme ISO-8859-1 par le récepteur.

Par exemple, si vous exécutez le script Python suivant:

# -*- encoding: utf-8 -*- 

import json 

data = {'name': u'André'} 
print('data: {0}'.format(repr(data))) 

code = json.dumps(data) 
print('code: {0}'.format(repr(code))) 

conv = json.loads(code) 
print('conv: {0}'.format(repr(conv))) 

name = conv['name'] 
print(u'Name is {0}'.format(name)) 

La sortie devrait ressembler à:

data: {'name': u'Andr\xe9'} 
code: '{"name": "Andr\\u00e9"}' 
conv: {u'name': u'Andr\xe9'} 
Name is André 

Gestion unicode en Python 2.x peut parfois devenir une nuisance. Malheureusement, Django ne supporte pas encore Python 3.

+0

+1 mais je ne vois pas comment Python 3.x empêche les gens de faire 'rawbytes.decode ('latin1')' au lieu de 'rawbytes.decode ('utf8')'. Les données ne sont PAS stockées et transmises en Unicode; il est toujours encodé en octets, et le récepteur doit encore savoir * quel * encodage pour le décoder. –

+0

Qu'est-ce que vous utilisez pour vérifier la valeur réelle de \ u00c3, \ 00a9 ou \ u00e9? –

+0

@John Machin: Vous avez raison. Cependant, dans la plupart des cas, le récepteur devrait être capable de dériver l'encodage. Par exemple, si un serveur Web envoie une page html avec un formulaire dans un encodage particulier, pratiquement tous les navigateurs renverront les données du formulaire dans le même encodage. @Thierry Lam: Si vous ne pouvez pas trouver une visionneuse de carte de caractères sous certains menus d'accessoires sur votre système, essayez google pour "codes-codes Unicode". Exemple de site: http: // inamidst.com/trucs/unidata / –

Questions connexes