Python: json.loads mengembalikan item yang diawali dengan 'u'

161

Saya akan menerima bentuk string JSON yang dikodekan Obj-C, dan saya mendekode string dummy (untuk saat ini) seperti kode di bawah ini. Output saya keluar dengan karakter 'u' mengawali setiap item:

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

Bagaimana JSON menambahkan char unicode ini? Apa cara terbaik untuk menghapusnya?

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
sumber
7
Python memang punya masalah di sini. Semuanya tidak dingin. Saya mendapatkan kesalahan dalam string yang dibuat oleh Python ketika saya mencoba dan menulis string ini ke file. Sebagai contoh ketika python mengambil "53" dari JSON itu mengubahnya menjadi u'53 'dan mencoba untuk menulisnya ke file sebagai karakter hex u' \ xe1 'yang menyebabkan Python untuk mengambil string yang sangat baik dan muntah di atasnya: JSON: {"sa_BstDeAv": "53", "sa_BwVUpMx" ... PYTHON: {u'sa_BstDeAv ': u'53', u'sa_BwVUpMx '... ERROR ON WRITE: Kesalahan nilai (' ascii 'codec tidak dapat menyandikan karakter u '\ xe1' di posisi 5: ordinal tidak dalam jangkauan (128))
David Urry
@ janehouse jawaban yang tepat di sini adalah jawaban oleh jdi. Saya benar-benar berpikir Anda harus mengubahnya.
Dekel

Jawaban:

168

Awalan u- artinya Anda memiliki string Unicode. Ketika Anda benar-benar menggunakan string, itu tidak akan muncul di data Anda. Jangan terlempar oleh hasil cetak.

Misalnya, coba ini:

print mail_accounts[0]["i"]

Anda tidak akan melihat Anda.

Ned Batchelder
sumber
5
Jawaban Anda adalah yang paling berguna yang saya dapatkan, dan saya pikir penanya pertanyaan ini akan sangat menghargainya: stackoverflow.com/questions/956867/…
jimh
1
Terima kasih banyak ! saya bingung untuk surat Anda begitu lama
ketan khandagale
Kecuali jika Anda menyalin dan menempelkannya, Anda memiliki sejumlah besar udata Anda. Terus terang, mencetak uuntuk menunjukkan itu adalah string Unicode adalah salah satu kesalahan terburuk tentang Python. Benar-benar konyol. Mengapa tidak mencetak asebelum setiap string jika itu ASCII? Sebuah ijika itu sebuah integer?
Snowcrash
Dalam Python 2, string Unicode adalah tipe yang berbeda dari string byte, sehingga repr data menyertakan awalan untuk menunjukkan itu. Ini bukan tentang apa isi yang terjadi, ini tentang jenisnya. Awalan u baik-baik saja jika Anda menempelkan konten kembali ke program Python. Jika tidak, mungkin Anda ingin menggunakan json.dumps () sebagai gantinya.
Ned Batchelder
Anda harus menggunakan string untuk mencari kamus json. Namun Anda mungkin tidak menggunakan operator titik.
Maddocks
151

Semuanya keren, bung. The 'u' adalah hal yang baik, ini menunjukkan bahwa string bertipe Unicode di python 2.x.

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

Seorang pria
sumber
71
Saya suka nada sangat dingin yang satu ini. +1 untuk jawaban (yang benar) yang membuat saya tersenyum.
mgilson
19
Just, chill ... (┛◉Д◉) ┛ 彡 ┻━┻
fulvio
31
Itu adalah jawaban paling santai yang pernah saya baca di StackOverflow.
aanrv
3
☮ ☮ ☮ Perdamaian ☮ ☮ ☮
sr9yar
54

The d3cetak di bawah ini adalah salah satu yang Anda cari (yang merupakan kombinasi dari kesedihan dan beban) :)

Memiliki:

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

Cetakan:

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"}
Air raksa
sumber
3
Hah? json.dumpsmengkonversi dict kembali ke string (JSON-encoded). Bukan itu yang ingin dilakukan OP. -1.
Mark Amery
10
Tetapi jika Anda menggunakannya bersama-sama dengan json.loads itu mengeluarkan kamus tanpa karakter yang disandikan yang merupakan jawaban untuk pertanyaan (ini adalah cetak d3 di atas) baca jawabannya dengan baik!
Merkurius
8

The uawalan berarti bahwa mereka string unicode daripada 8-bit string. Cara terbaik untuk tidak menampilkan uawalan adalah beralih ke Python 3, di mana string adalah unicode secara default. Jika itu bukan opsi, strkonstruktor akan mengkonversi dari unicode ke 8-bit, jadi cukup loop rekursif atas hasilnya dan dikonversi unicodeke str. Namun, mungkin yang terbaik adalah membiarkan string sebagai unicode.

Abe Karplus
sumber
8

Unicode adalah tipe yang tepat di sini. Dokumen JSONDecoder menjelaskan tabel konversi dan menyatakan bahwa objek string json didekodekan menjadi objek 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

"Pengkodean menentukan pengodean yang digunakan untuk menginterpretasikan objek str yang didekode oleh instance ini (secara default UTF-8)."

jdi
sumber
7

Karakter 'u' yang ditambahkan ke objek menandakan bahwa objek dikodekan dalam "unicode".

Jika Anda ingin menghapus karakter 'u' dari objek Anda, Anda dapat melakukan ini:

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

Mari kita checkout dari 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'}]
Nivesh Krishna
sumber
Saya sarankan setiap pemula cukup mencoba skrip ini dan voila Anda memiliki skrip untuk dikonversi ~ dari ~ u'JSON output :) ... jika seseorang hanya dapat menambahkan stdin ke skrip, dan format json pada akhirnya, Anda siap untuk berangkat!
Jordan Gee
4

Saya terus mengalami masalah ini ketika mencoba untuk menangkap data JSON dalam log dengan loggingpustaka Python , untuk keperluan debugging dan troubleshooting. Mendapatkan ukarakter adalah gangguan nyata ketika Anda ingin menyalin teks dan menempelkannya ke kode Anda di suatu tempat.

Seperti yang semua orang akan katakan kepada Anda, ini karena itu adalah representasi Unicode, dan itu bisa berasal dari fakta bahwa Anda sudah terbiasa json.loads()memuat data dari string di tempat pertama.

Jika Anda ingin representasi JSON di log, tanpa uawalan, triknya adalah menggunakan json.dumps()sebelum logout . Sebagai contoh:

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
sumber
1
Ini benar-benar harus menjadi jawaban terbaik, Anda benar-benar tidak "dilucuti" dalam banyak konteks. Terima kasih banyak atas ini!
Jessica Pennell
1

Coba ini:

mail_accounts [0] .encode ("ascii")

2nd Sight Lab
sumber
Jawaban tanpa penjelasan apa pun nyaris tidak berguna. Silakan coba tambahkan beberapa informasi seperti mengapa ini bisa membantu.
Abhilash Chandran
Secara pribadi, saya menemukan jawaban yang panjang dengan terlalu banyak informasi yang tidak perlu mengganggu. Jawaban di atas sudah menjelaskan bahwa nilainya adalah unicode dan perlu dikonversi ke ascii jadi saya tidak mengulangi semua itu. Hanya menunjukkan cara yang lebih sederhana untuk mendapatkan nilai. Jika ada yang memiliki masalah dalam menggunakan jawaban ini, tanyakan saja dan saya senang menjelaskan lebih lanjut! Terima kasih
2nd Sight Lab
Ini sebenarnya satu-satunya jawaban yang menunjukkan secara ringkas bagaimana mengkodekan ulang setiap string ke 'normal' tanpa melalui (yang pasti tidak efisien) json.loads, json.dumps cycle.
Ed Randall
0

Cukup ganti u 'dengan satu kutipan ...

print (str.replace(mail_accounts,"u'","'"))
Mikematik
sumber