Python: json.loads restituisce gli elementi con il prefisso 'u'


161

Riceverò una stringa codificata JSON da Obj-C, e sto decodificando una stringa fittizia (per ora) come il codice qui sotto. Il mio output esce con il carattere 'u' che precede ogni elemento:

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

In che modo JSON sta aggiungendo questo carattere Unicode? Qual è il modo migliore per rimuoverlo?

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 ha un problema qui. Non tutto è freddo. Ricevo errori nelle stringhe create da Python quando provo a scrivere queste stringhe in un file. Ad esempio, quando python prende "53" da JSON, lo trasforma in u'53 'e tenta di scriverlo in un file come carattere esadecimale u' \ xe1 'che fa sì che Python prenda una stringa perfettamente valida e ci vomiti sopra: JSON: {"sa_BstDeAv": "53", "sa_BwVUpMx" ... PYTHON: {u'sa_BstDeAv ': u'53', u'sa_BwVUpMx '... ERRORE ON WRITE: errore valore (il codec' ascii 'non può codificare carattere u '\ xe1' in posizione 5: ordinale non nel raggio (128))
David Urry

@janehouse la risposta giusta qui è la risposta di jdi Penso davvero che dovresti cambiarlo.
Dekel,

Risposte:


168

Il prefisso u significa solo che hai una stringa Unicode. Quando usi davvero la stringa, questa non apparirà nei tuoi dati. Non essere generato dall'output stampato.

Ad esempio, prova questo:

print mail_accounts[0]["i"]

Non vedrai una u.


5
La tua risposta è stata quella più utile che ho ottenuto, e penso che il richiedente di questa domanda sarebbe davvero apprezzato: stackoverflow.com/questions/956867/...
jimh

1
Grazie mille ! ero confuso per la tua lettera per così tanto tempo
ketan khandagale,

Tranne se lo copi e incolli hai una grande quantità di messaggi udi posta elettronica. Francamente, stampare a uper indicare che è una stringa Unicode è uno dei peggiori errori su Python. Assolutamente ridicolo. Perché non stampare un aprima di ogni stringa se è ASCII? An ise è un numero intero?
Snowcrash,

In Python 2, le stringhe Unicode sono di tipo diverso rispetto alle stringhe di byte, quindi il repr dei dati include il prefisso per indicarlo. Non si tratta di quale sia il contenuto, ma del tipo. Il prefisso u va bene se stai incollando il contenuto in un programma Python. In caso contrario, forse si desidera utilizzare json.dumps () invece.
Ned Batchelder il

Devi usare la stringa per cercare nel dizionario di json. tuttavia non è possibile utilizzare l'operatore punto.
Maddocks


54

La d3stampa qui sotto è quella che stai cercando (che è la combinazione di discariche e carichi) :)

avere:

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

stampe:

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
Eh? json.dumpsconverte il dict in una stringa (codificata JSON). Non è quello che l'OP voleva fare. -1.
Mark Amery,

10
Ma se lo usi insieme a json.loads genera il dizionario senza i caratteri codificati con una risposta alla domanda (questa è la stampa d3 sopra) leggi bene la risposta!
Mercurio,

8

Il uprefisso significa che quelle stringhe sono unicode anziché stringhe a 8 bit. Il modo migliore per non mostrare il uprefisso è passare a Python 3, dove le stringhe sono unicode per impostazione predefinita. Se questa non è un'opzione, il strcostruttore convertirà da Unicode a 8 bit, quindi esegui semplicemente il ciclo ricorsivo sul risultato e convertilo unicodein str. Tuttavia, è probabilmente meglio lasciare le stringhe come unicode.


8

Unicode è un tipo appropriato qui. I documenti JSONDecoder descrivono la tabella di conversione e affermano che gli oggetti stringa json sono decodificati in oggetti 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

"La codifica determina la codifica utilizzata per interpretare qualsiasi oggetto str decodificato da questa istanza (UTF-8 per impostazione predefinita)."


7

Quei caratteri 'u' che vengono aggiunti a un oggetto indicano che l'oggetto è codificato in "unicode".

Se vuoi rimuovere quei caratteri 'u' dal tuo oggetto puoi farlo:

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

Facciamo il checkout dalla shell di 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'}]

Suggerisco a tutti i principianti di provare semplicemente questo script e voilà hai uno script per convertire ~ dall'output di ~ u'JSON :) ... se uno può solo aggiungere stdin allo script e il formato json alla fine, sei pronto ad andare!
Jordan Gee,

4

Ho continuato a riscontrare questo problema durante il tentativo di acquisire i dati JSON nel registro con la logginglibreria Python , a scopo di debug e risoluzione dei problemi. Ottenere il upersonaggio è una vera seccatura quando vuoi copiare il testo e incollarlo nel tuo codice da qualche parte.

Come tutti ti diranno, questo è perché è una rappresentazione Unicode e potrebbe derivare dal fatto che hai usato json.loads()per caricare i dati da una stringa in primo luogo.

Se si desidera la rappresentazione JSON nel registro, senza il uprefisso, il trucco è utilizzarejson.dumps() prima di disconnettersi. Per esempio:

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
Questa dovrebbe davvero essere la risposta migliore, in tutti i contesti non devi assolutamente "spogliarti". Grazie mille per questo!
Jessica Pennell,

1

Prova questo:

mail_accounts [0] .encode ( "ascii")


Una risposta senza alcuna spiegazione è quasi inutile. Si prega di provare ad aggiungere alcune informazioni come perché questo potrebbe aiutare.
Abhilash Chandran,

Personalmente, trovo lunghe risposte con troppe informazioni inutili che distraggono. Le risposte sopra spiegano già che il valore è unicode e deve essere convertito in ascii, quindi non ripeterò tutto ciò. Sto solo mostrando un modo più semplice per ottenere il valore. Se qualcuno ha problemi ad usare questa risposta, basta chiedere e sono felice di spiegare ulteriormente! Grazie
2nd Sight Lab il

Questa è in realtà l'unica risposta che mostra in modo conciso come ricodificare ogni stringa in 'normale' senza passare attraverso un ciclo (che deve essere ridicolmente inefficiente) json.loads, json.dumps.
Ed Randall,

0

Basta sostituire l'U 'con una sola citazione ...

print (str.replace(mail_accounts,"u'","'"))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.