642 votes

Enregistrement des textes utf-8 dans json.dumps comme UTF8, et non comme la séquence d’échappement \u

exemple de code:

>>> import json
>>> json_stringv json.dumps("ברי צקלה")
>>> print json_string
"\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4"

Le problème: il n'est pas lisible par l'homme. Mon (smart), les utilisateurs souhaitent vérifier ou modifier des fichiers texte avec JSON décharges. (et je préfère ne pas utiliser le XML)

Est-il possible de sérialiser des objets en utf-8 chaîne json (au lieu de \uXXXX ) ?

ce n'aide pas:

>>> output = json_string.decode('string-escape')
"\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4"

cela fonctionne, mais si tous les sous-objets est un python unicode et pas en utf-8, il va de vidage de la poubelle:

>>> #### ok:
>>> s= json.dumps( "ברי צקלה", ensure_ascii=False)    
>>> print json.loads(s)   
ברי צקלה

>>> #### NOT ok:
>>> d={ 1: "ברי צקלה", 2: u"ברי צקלה" }
>>> print d
{1: '\xd7\x91\xd7\xa8\xd7\x99 \xd7\xa6\xd7\xa7\xd7\x9c\xd7\x94', 
 2: u'\xd7\x91\xd7\xa8\xd7\x99 \xd7\xa6\xd7\xa7\xd7\x9c\xd7\x94'}
>>> s = json.dumps( d, ensure_ascii=False, encoding='utf8')
>>> print json.loads(s)['1']
ברי צקלה
>>> print json.loads(s)['2']
××¨× ×¦×§××

j'ai cherché sur le json.les vidages de documentation, mais ne pouvait pas trouver quelque chose d'utile.

Edit - Solution(?):

je vais essayer de résumer les commentaires et les réponses par Martijn Pieters:

(edit: 2ème pensée après @Sébastien commentaire et environ un an plus tard)

  1. il y a peut-être pas est une solution intégrée en json.décharges.

  2. je vais devoir convertir toutes les chaînes à UTF8 Unicode l'objet avant d'être JSON-ed. je vais utiliser la Marque, la fonction qui convertit les chaînes recuresively dans un objet imbriqué

  3. l'exemple que j'ai donné, dépend beaucoup trop sur mon ordinateur & environnement IDE, et n'exécute pas les mêmes sur tous les ordinateurs.

Merci tout le monde :)

929voto

Martijn Pieters Points 271458

Utiliser l' ensure_ascii=False commutateur json.dumps(), puis l'encoder la valeur de l'UTF-8 manuellement:

>>> json_string = json.dumps(u"ברי צקלה", ensure_ascii=False).encode('utf8')
>>> json_string
'"\xd7\x91\xd7\xa8\xd7\x99 \xd7\xa6\xd7\xa7\xd7\x9c\xd7\x94"'
>>> print json_string
"ברי צקלה"

Si vous écrivez à un fichier, vous pouvez utiliser io.open() au lieu de open() pour produire un fichier d'objet qui encode les valeurs Unicode pour vous comme vous l'écrivez, puis utilisez json.dump() plutôt d'écrire dans ce fichier:

with io.open('filename', 'w', encoding='utf8') as json_file:
    json.dump(u"ברי צקלה", json_file, ensure_ascii=False)

En Python 3, le haut- open() est un alias pour io.open(). Notez qu'il y a un bug dans l' json module où l' ensure_ascii=False indicateur peut produire un mélange d' unicode et str objets. La solution de contournement pour Python 2 est alors:

with io.open('filename', 'w', encoding='utf8') as json_file:
    data = json.dumps(u"ברי צקלה", ensure_ascii=False).decode('utf8')
    try:
        json_file.write(data)
    except TypeError:
        # Decode data to Unicode first
        json_file.write(data.decode('utf8'))

Si vous êtes de passage dans les chaînes d'octets (type str en Python 2, bytes en Python 3) encodé en UTF-8, assurez-vous de configurer l' encoding mot-clé:

>>> d={ 1: "ברי צקלה", 2: u"ברי צקלה" }
>>> d
{1: '\xd7\x91\xd7\xa8\xd7\x99 \xd7\xa6\xd7\xa7\xd7\x9c\xd7\x94', 2: u'\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4'}

>>> s=json.dumps(d, ensure_ascii=False, encoding='utf8')
>>> s
u'{"1": "\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4", "2": "\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4"}'
>>> json.loads(s)['1']
u'\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4'
>>> json.loads(s)['2']
u'\u05d1\u05e8\u05d9 \u05e6\u05e7\u05dc\u05d4'
>>> print json.loads(s)['1']
ברי צקלה
>>> print json.loads(s)['2']
ברי צקלה

Notez que votre deuxième exemple est pas valide Unicode; vous lui avez donné octets UTF-8 comme un caractère littéral, ce serait de ne jamais le travail:

>>> s = u'\xd7\x91\xd7\xa8\xd7\x99 \xd7\xa6\xd7\xa7\xd7\x9c\xd7\x94'
>>> print s
××¨× ×¦×§××
>>> print s.encode('latin1').decode('utf8')
ברי צקלה

Seulement quand j'ai codé la chaîne Latin 1 (dont unicode codepoints carte un-à-un à octets) puis décoder comme UTF-8 voyez-vous la sortie attendue. Qui n'a rien à voir avec JSON et tout à voir avec la que vous vous trompez d'entrée. Le résultat est appelé un Mojibake.

Si vous avez obtenu cette valeur Unicode à partir d'une chaîne littérale, il a été décodé en utilisant le mauvais codec. Il pourrait être votre terminal est mal configuré, ou que votre éditeur de texte enregistré votre code source à l'aide d'un codec différent que ce que vous avez dit à Python pour lire le fichier. Ou vous de source à partir d'une bibliothèque qui a appliqué le mauvais codec. Tout cela n'a rien à voir avec la librairie JSON.

30voto

monitorius Points 133

Qu’en est-il `` ?

-3voto

Ryan X Points 53

À l'aide de ensure_ascii=False en json.dumps est la bonne direction pour résoudre ce problème, comme l'a souligné par Martijn. Cependant, cela peut soulever une exception:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 1: ordinal not in range(128)

Vous avez besoin de paramètres supplémentaires dans les deux site.py ou sitecustomize.py pour définir votre sys.getdefaultencoding() correct. site.py est dans lib/python2.7/ et sitecustomize.py est dans lib/python2.7/site-packages.

Si vous souhaitez utiliser site.py sous def setencoding(): change le premier si la valeur 0: si 1: de sorte que python d'utilisation de votre système d'exploitation locale de l'.

Si vous préférez utiliser sitecustomize.py qui ne peut exister que si vous n'avez pas encore créé il. simplement mettre ces lignes:

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

Ensuite, vous pouvez faire quelques Chinois json sortie au format utf-8, comme:

name = {"last_name": u"王"}
json.dumps(name, ensure_ascii=False)

Vous obtiendrez une codé en utf-8 chaîne de caractères, plutôt que de \u échappé à la chaîne json.

Pour vérifier votre encodage par défaut:

print sys.getdefaultencoding()

Vous devriez obtenir "utf-8" ou "UTF-8" pour vérifier votre site.py ou sitecustomize.py les paramètres.

Veuillez noter que vous ne pouvez pas faire sys.setdefaultencoding("utf-8") à l'interactive python console.

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