Python: json.loads zwraca elementy z przedrostkiem „u”

161

Otrzymam ciąg zakodowany w formacie JSON w postaci Obj-C i dekoduję fikcyjny ciąg (na razie) taki jak w poniższym kodzie. Moje dane wyjściowe są wyświetlane ze znakiem „u” poprzedzającym każdą pozycję:

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

W jaki sposób JSON dodaje ten znak Unicode? Jak najlepiej go usunąć?

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
janeh
źródło
7
Python ma tutaj problem. Nie wszystko jest chłodne. Otrzymuję błędy w ciągach, które tworzy Python, kiedy próbuję zapisać te ciągi do pliku. Na przykład, gdy Python pobiera „53” z JSON, zamienia go na u'53 'i próbuje zapisać go do pliku jako znak szesnastkowy u' \ xe1 ', co powoduje, że Python pobiera idealnie dobry ciąg i wymiotuje: JSON: {"sa_BstDeAv": "53", "sa_BwVUpMx" ... PYTHON: {u'sa_BstDeAv ': u'53', u'sa_BwVUpMx '... ERROR ON WRITE: Błąd wartości (kodek' ascii 'nie może zakodować znak u '\ xe1' na pozycji 5: liczba porządkowa poza zakresem (128))
David Urry
@janehouse Właściwa odpowiedź to odpowiedź jdi. Naprawdę uważam, że powinieneś to zmienić.
Dekel

Odpowiedzi:

168

Prefiks u- oznacza po prostu, że masz ciąg znaków Unicode. Kiedy naprawdę używasz ciągu, nie pojawi się on w twoich danych. Nie daj się wyrzucić przez wydruk.

Na przykład spróbuj tego:

print mail_accounts[0]["i"]

Nie zobaczysz u.

Ned Batchelder
źródło
5
Twoja odpowiedź była najbardziej użyteczna, jaką otrzymałem i myślę, że osoba, która zadała to pytanie, naprawdę by to doceniła: stackoverflow.com/questions/956867/ ...
jimh
1
Dziękuję bardzo ! tak długo
byłem zdezorientowany tym listem
Z wyjątkiem sytuacji, gdy skopiujesz go i wkleisz, masz ogromną liczbę uplików w swoich danych. Szczerze mówiąc, wydrukowanie a, uaby wskazać, że jest to łańcuch Unicode, jest jednym z najgorszych błędów w Pythonie. Całkowicie śmieszne. Dlaczego nie wypisać aprzed każdym ciągiem znaków ASCII? A ijeśli jest to liczba całkowita?
Snowcrash
W Pythonie 2 ciągi Unicode są innego typu niż ciągi bajtów, więc repr danych zawiera prefiks, który to wskazuje. Nie chodzi o to, jaka jest zawartość, chodzi o typ. Prefiks u jest w porządku, jeśli wklejasz zawartość z powrotem do programu w Pythonie. Jeśli nie, być może chcesz zamiast tego użyć json.dumps ().
Ned Batchelder
Musisz użyć ciągu, aby przeszukać słownik json. nie możesz jednak używać operatora kropki.
Maddocks
151

Wszystko w porządku, stary. Litera „u” to dobra rzecz, wskazuje, że w pythonie 2.x łańcuch jest typu Unicode.

http://docs.python.org/2/howto/unicode.html#the-unicode-type

Mężczyzna
źródło
71
Podoba mi się bardzo chłodny ton tego. +1 za (poprawną) odpowiedź, która sprawiła, że ​​się uśmiechnąłem.
mgilson
19
Po prostu wyluzuj ... (┛◉Д◉) ┛ 彡 ┻━┻
fulvio
31
To była najbardziej relaksująca odpowiedź, jaką przeczytałem w StackOverflow.
aanrv
3
☮ ☮ ☮ Pokój ☮ ☮ ☮
sr9yar
54

Poniższy d3wydruk to ten, którego szukasz (czyli połączenie zrzutów i ładunków) :)

Mający:

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

Wydruki:

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"}
Rtęć
źródło
3
Co? json.dumpskonwertuje dict z powrotem na ciąg (zakodowany w formacie JSON). Nie tego chciał zrobić OP. -1.
Mark Amery,
10
Ale jeśli użyjesz go razem z json.loads, wyprowadza słownik bez zakodowanych znaków, co jest odpowiedzią na pytanie (to jest d3 print powyżej), przeczytaj dobrze odpowiedź!
Mercury,
8

Te uśrodki prefiks, że te ciągi są Unicode zamiast 8-bitowe ciągi. Najlepszym sposobem, aby nie pokazywać uprefiksu, jest przełączenie się na Python 3, w którym ciągi znaków są domyślnie unicode. Jeśli to nie jest opcja, strkonstruktor konwertuje z Unicode na 8-bitowy, więc po prostu zapętlaj rekurencyjnie wynik i przekonwertuj unicodena str. Jednak prawdopodobnie najlepiej jest pozostawić ciągi jako Unicode.

Abe Karplus
źródło
8

Unicode jest tutaj odpowiednim typem. Dokumentacja JSONDecoder opisuje tabelę konwersji i stwierdza, że ​​obiekty stringów json są dekodowane do obiektów 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

„kodowanie określa kodowanie używane do interpretacji dowolnych obiektów str dekodowanych przez tę instancję (domyślnie UTF-8)”.

jdi
źródło
7

Te znaki „u” dołączane do obiektu oznaczają, że obiekt jest zakodowany w „unicode”.

Jeśli chcesz usunąć te znaki 'u' ze swojego obiektu, możesz to zrobić:

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

Sprawdźmy z powłoki Pythona

>>> 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'}]
Nivesh Krishna
źródło
Proponuję każdemu nowicjuszowi po prostu wypróbować ten skrypt i voila, masz własny skrypt do konwersji ~ z wyjścia ~ u'JSON :) ... jeśli można tylko dodać stdin do skryptu, a na końcu format json, jesteś gotowy do wyjścia!
Jordan Gee,
4

Ciągle napotykałem ten problem, próbując przechwycić dane JSON w dzienniku za pomocą loggingbiblioteki Python , w celu debugowania i rozwiązywania problemów. Uzyskanie uznaku jest naprawdę uciążliwe, gdy chcesz skopiować tekst i wkleić go gdzieś w swoim kodzie.

Jak wszyscy powiedzą, dzieje się tak dlatego, że jest to reprezentacja Unicode i może to wynikać z faktu, że json.loads()w pierwszej kolejności ładowałeś dane z łańcucha.

Jeśli chcesz, aby w dzienniku była reprezentacja JSON, bez uprefiksu, sztuczka polega na użyciu json.dumps()przed wylogowaniem. Na przykład:

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'}
jonatan
źródło
1
To naprawdę powinna być najlepsza odpowiedź, w wielu kontekstach absolutnie nie „po prostu daj się rozebrać”. Dziękuję bardzo za to!
Jessica Pennell
1

Spróbuj tego:

mail_accounts [0] .encode („ascii”)

2nd Sight Lab
źródło
Odpowiedź bez żadnego wyjaśnienia jest prawie bezużyteczna. Spróbuj dodać kilka informacji, np. Dlaczego miałoby to pomóc.
Abhilash Chandran
Osobiście uważam, że długie odpowiedzi ze zbyt dużą ilością niepotrzebnych informacji rozpraszają uwagę. Powyższe odpowiedzi już wyjaśniają, że wartość jest unicode i musi zostać przekonwertowana na ascii, więc nie powtarzam tego wszystkiego. Po prostu pokazuję prostszy sposób uzyskania wartości. Jeśli ktoś ma problemy z używaniem tej odpowiedzi, po prostu zapytaj, a ja chętnie wyjaśnię dalej! Dzięki
2nd Sight Lab
W rzeczywistości jest to jedyna odpowiedź, która zwięźle pokazuje, jak przekodować każdy ciąg na „normalny” bez przechodzenia przez (co musi być absurdalnie nieefektywne) cykl json.loads, json.dumps.
Ed Randall
0

Wystarczy zastąpić u 'pojedynczym cudzysłowem ...

print (str.replace(mail_accounts,"u'","'"))
Mikematic
źródło