Python: json.loads renvoie les éléments préfixés par 'u'


161

Je vais recevoir une chaîne codée JSON sous la forme Obj-C, et je décode une chaîne factice (pour l'instant) comme le code ci-dessous. Ma sortie sort avec le caractère 'u' préfixant chaque élément:

[{u'i': u'imap.gmail.com', u'p': u'aaaa'}, {u'i': u'333imap.com', u'p': u'bbbb'}...

Comment JSON ajoute-t-il ce caractère unicode? Quelle est la meilleure façon de le supprimer?

mail_accounts = []
da = {}
try:
    s = '[{"i":"imap.gmail.com","p":"aaaa"},{"i":"imap.aol.com","p":"bbbb"},{"i":"333imap.com","p":"ccccc"},{"i":"444ap.gmail.com","p":"ddddd"},{"i":"555imap.gmail.com","p":"eee"}]'
    jdata = json.loads(s)
    for d in jdata:
        for key, value in d.iteritems():
            if key not in da:
                da[key] = value
            else:
                da = {}
                da[key] = value
        mail_accounts.append(da)
except Exception, err:
    sys.stderr.write('Exception Error: %s' % str(err))

print mail_accounts

7
Python a un problème ici. Tout n'est pas froid. J'obtiens des erreurs dans les chaînes créées par Python lorsque j'essaie d'écrire ces chaînes dans un fichier. Par exemple, lorsque python prend "53" de JSON, il le transforme en u'53 'et tente de l'écrire dans un fichier en tant que caractère hexadécimal u' \ xe1 ', ce qui oblige Python à prendre une chaîne parfaitement bonne et à vomir dessus: JSON: {"sa_BstDeAv": "53", "sa_BwVUpMx" ... PYTHON: {u'sa_BstDeAv ': u'53', u'sa_BwVUpMx '... ERROR ON WRITE: Erreur de valeur (le codec' ascii 'ne peut pas encoder caractère u '\ xe1' en position 5: ordinal hors de la plage (128))
David Urry

@janehouse la bonne réponse ici est la réponse de jdi Je pense vraiment que vous devriez la changer.
Dekel

Réponses:


168

Le préfixe u signifie simplement que vous avez une chaîne Unicode. Lorsque vous utilisez vraiment la chaîne, elle n'apparaîtra pas dans vos données. Ne soyez pas renversé par la sortie imprimée.

Par exemple, essayez ceci:

print mail_accounts[0]["i"]

Vous ne verrez pas de u.


5
Votre réponse a été la plus utile que j'ai eue, et je pense que le demandeur de cette question l'aurait vraiment appréciée: stackoverflow.com/questions/956867/…
jimh

1
Merci beaucoup ! J'ai été confus pour u '' lettre pendant si longtemps
ketan khandagale

Sauf si vous le copiez et collez, vous avez une grande quantité de us dans vos données. Franchement, imprimer un upour indiquer qu'il s'agit d'une chaîne Unicode est l'une des pires erreurs concernant Python. Absolument ridicule. Pourquoi ne pas imprimer une aavant chaque chaîne si elle est ASCII? Et isi c'est un entier?
Snowcrash

En Python 2, les chaînes Unicode sont d'un type différent des chaînes d'octets, donc la repr des données inclut le préfixe pour l'indiquer. Il ne s'agit pas de ce que le contenu se trouve être, mais du type. Le préfixe u convient si vous collez le contenu dans un programme Python. Sinon, vous voudrez peut-être utiliser json.dumps () à la place.
Ned Batchelder

Vous devez utiliser la chaîne pour rechercher le dictionnaire de json. vous ne pouvez cependant pas utiliser l'opérateur point.
Maddocks


54

L' d3impression ci-dessous est celle que vous recherchez (qui est la combinaison de décharges et de charges) :)

Ayant:

import json

d = """{"Aa": 1, "BB": "blabla", "cc": "False"}"""

d1 = json.loads(d)              # Produces a dictionary out of the given string
d2 = json.dumps(d)              # Produces a string out of a given dict or string
d3 = json.dumps(json.loads(d))  # 'dumps' gets the dict from 'loads' this time

print "d1:  " + str(d1)
print "d2:  " + d2
print "d3:  " + d3

Impressions:

d1:  {u'Aa': 1, u'cc': u'False', u'BB': u'blabla'}
d2:  "{\"Aa\": 1, \"BB\": \"blabla\", \"cc\": \"False\"}"
d3:  {"Aa": 1, "cc": "False", "BB": "blabla"}

3
Hein? json.dumpsconvertit le dict en une chaîne (codée JSON). Ce n'est pas ce que le PO voulait faire. -1.
Mark Amery

10
Mais si vous l'utilisez avec json.loads, il génère le dictionnaire sans les caractères encodés, ce qui est une réponse à la question (c'est d3 print ci-dessus), lisez bien la réponse!
Mercury

8

Le upréfixe signifie que ces chaînes sont unicode plutôt que des chaînes de 8 bits. La meilleure façon de ne pas afficher le upréfixe est de passer à Python 3, où les chaînes sont unicode par défaut. Si ce n'est pas une option, le strconstructeur convertira de Unicode en 8 bits, il suffit donc de boucler récursivement sur le résultat et de le convertir unicodeen str. Cependant, il est probablement préférable de laisser les chaînes au format Unicode.


8

Unicode est un type approprié ici. La documentation JSONDecoder décrit la table de conversion et indique que les objets chaîne json sont décodés en objets Unicode

https://docs.python.org/2/library/json.html#encoders-and-decoders

JSON                    Python
==================================
object                  dict
array                   list
string                  unicode
number (int)            int, long
number (real)           float
true                    True
false                   False
null                    None

"l'encodage détermine l'encodage utilisé pour interpréter les objets str décodés par cette instance (UTF-8 par défaut)."


7

Ces caractères «u» ajoutés à un objet signifient que l'objet est codé en «unicode».

Si vous souhaitez supprimer ces caractères «u» de votre objet, vous pouvez le faire:

import json, ast
jdata = ast.literal_eval(json.dumps(jdata)) # Removing uni-code chars

Vérifions à partir du shell python

>>> import json, ast
>>> jdata = [{u'i': u'imap.gmail.com', u'p': u'aaaa'}, {u'i': u'333imap.com', u'p': u'bbbb'}]
>>> jdata = ast.literal_eval(json.dumps(jdata))
>>> jdata
[{'i': 'imap.gmail.com', 'p': 'aaaa'}, {'i': '333imap.com', 'p': 'bbbb'}]

Je suggère à chaque débutant d'essayer simplement ce script et voilà, vous avez vous-même un script à convertir ~ à partir de la sortie ~ u'JSON :) ... si l'on ne peut ajouter que stdin au script, et le format json à la fin, vous êtes Prêt à partir!
Jordan Gee

4

J'ai continué à rencontrer ce problème en essayant de capturer des données JSON dans le journal avec la loggingbibliothèque Python , à des fins de débogage et de dépannage. Obtenir le ucaractère est une véritable nuisance lorsque vous souhaitez copier le texte et le coller quelque part dans votre code.

Comme tout le monde vous le dira, c'est parce qu'il s'agit d'une représentation Unicode, et cela peut venir du fait que vous avez utilisé json.loads()pour charger les données à partir d'une chaîne en premier lieu.

Si vous voulez la représentation JSON dans le journal, sans le upréfixe, l'astuce consiste à utiliser json.dumps()avant de la déconnecter. Par exemple:

import json
import logging

# Prepare the data
json_data = json.loads('{"key": "value"}')

# Log normally and get the Unicode indicator
logging.warning('data: {}'.format(json_data))
>>> WARNING:root:data: {u'key': u'value'}

# Dump to a string before logging and get clean output!
logging.warning('data: {}'.format(json.dumps(json_data)))
>>> WARNING:root:data: {'key': 'value'}

1
Cela devrait vraiment être la meilleure réponse, les «u» ne sont absolument pas «simplement supprimés» dans de nombreux contextes. Merci beaucoup pour cela!
Jessica Pennell

1

Essaye ça:

mail_accounts [0] .encode ("ascii")


Une réponse sans aucune explication est presque inutile. Veuillez essayer d'ajouter des informations comme pourquoi cela pourrait aider.
Abhilash Chandran le

Personnellement, je trouve les réponses longues avec trop d'informations inutiles distrayantes. Les réponses ci-dessus expliquent déjà que la valeur est unicode et doit être convertie en ascii donc je ne répète pas tout cela. Montrez simplement un moyen plus simple d'obtenir la valeur. Si quelqu'un a des problèmes en utilisant cette réponse, demandez simplement et je serai heureux de vous expliquer davantage! Merci
2nd Sight Lab

C'est en fait la seule réponse qui montre de manière concise comment recoder chaque chaîne en "normal" sans passer par un cycle (ce qui doit être ridiculement inefficace) json.loads, json.dumps.
Ed Randall

0

Remplacez simplement le u par un guillemet simple ...

print (str.replace(mail_accounts,"u'","'"))
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.