Python: json.loads retorna itens com o prefixo 'u'


161

Receberei uma sequência de caracteres codificada em JSON, Obj-C, e estou decodificando uma sequência fictícia (por enquanto) como o código abaixo. Minha saída sai com o caractere 'u' prefixando cada item:

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

Como o JSON está adicionando esse caractere unicode? Qual é a melhor maneira de removê-lo?

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 tem um problema aqui. Tudo não é frio. Estou recebendo erros nas strings que o Python cria quando tento gravar essas strings em um arquivo. Por exemplo, quando o python pega "53" do JSON, ele o transforma em u'53 'e tenta gravá-lo em um arquivo como caractere hexadecimal u' \ xe1 ', o que faz com que o Python pegue uma string perfeitamente boa e vomite: JSON: {"sa_BstDeAv": "53", "sa_BwVUpMx" ... PYTHON: {u'sa_BstDeAv ': u'53', u'sa_BwVUpMx '... ERRO AO ESCREVER: Erro de valor (o codec' ascii 'não pode codificar caractere u '\ xe1' na posição 5: ordinal fora do intervalo (128))
— David Urry

@ Janehouse a resposta certa aqui é a resposta por jdi Eu realmente acho que você deve mudar isso.
— Dekel

Respostas:


168

O prefixo u significa apenas que você tem uma string Unicode. Quando você realmente usa a string, ela não aparece nos seus dados. Não seja jogado pela saída impressa.

Por exemplo, tente o seguinte:

print mail_accounts[0]["i"]

Você não verá um u.


5
Sua resposta foi o mais útil que eu tenho, e acho que o autor da questão de esta questão teria realmente apreciado que: stackoverflow.com/questions/956867/...
— jimh

1
Muito obrigado ! Eu estava confuso para u '' carta por tanto tempo
— ketan khandagale

Exceto se você copiar e colar, você tem uma grande quantidade de us nos seus dados. Francamente, imprimir um upara indicar que é uma string Unicode é um dos piores erros do Python. Absolutamente ridículas. Por que não imprimir uma astring antes de cada string, se for ASCII? E ise for um número inteiro?
— Snowcrash

No Python 2, as strings Unicode são de um tipo diferente das strings de bytes, portanto, a repr dos dados inclui o prefixo para indicar isso. Não é sobre o conteúdo, é sobre o tipo. O prefixo u é bom se você estiver colando o conteúdo novamente em um programa Python. Caso contrário, talvez você queira usar o json.dumps ().
— Ned Batchelder

Você precisa usar a string para pesquisar no dicionário json. no entanto, você não pode usar o operador de ponto.
— Maddocks


54

A d3impressão abaixo é a que você está procurando (que é a combinação de lixões e cargas) :)

Tendo:

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

Impressões:

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
Hã? json.dumpsconverte o dict de volta em uma string (codificada em JSON). Não era isso que o OP queria fazer. -1.
— Mark Amery

10
Mas se você o usar junto com o json.loads, ele produzirá o dicionário sem os caracteres codificados, que é uma resposta para a pergunta (isto é, acima, no d3 print), leia bem a resposta!
— Mercury

8

O uprefixo significa que essas cadeias são unicode em vez de cadeias de 8 bits. A melhor maneira de não mostrar o uprefixo é mudar para Python 3, onde as strings são unicode por padrão. Se isso não for uma opção, o strconstrutor converterá de unicode para 8 bits, então simplesmente faça um loop recursivo sobre o resultado e converterá unicodeem str. No entanto, é provavelmente melhor deixar as seqüências como unicode.


8

Unicode é um tipo apropriado aqui. Os documentos JSONDecoder descrevem a tabela de conversão e afirmam que os objetos da string json são decodificados em objetos 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

"codificação determina a codificação usada para interpretar qualquer objeto str decodificado por esta instância (UTF-8 por padrão)."


7

Esses caracteres 'u' sendo anexados a um objeto significam que o objeto está codificado em "unicode".

Se você deseja remover os caracteres 'u' do seu objeto, você pode fazer isso:

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

Vamos fazer o checkout do python shell

>>> 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'}]

Eu sugiro que todo novato simplesmente experimente esse script e pronto, você tem um script para converter ~ da saída ~ u'JSON :) ... se alguém puder apenas adicionar stdin ao script e o formato json no final, você estará pronto para ir!
— Jordan Gee

4

Continuei com esse problema ao tentar capturar dados JSON no log com a loggingbiblioteca Python , para fins de depuração e solução de problemas. Obter o upersonagem é um verdadeiro incômodo quando você deseja copiar o texto e colá-lo em seu código em algum lugar.

Como todos dirão, isso ocorre porque é uma representação Unicode e pode vir do fato de você ter usado json.loads() os dados de uma string em primeiro lugar.

Se você deseja a representação JSON no log, sem o uprefixo, o truque é usar json.dumps()antes de fazer logout. Por exemplo:

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
Essa realmente deve ser a melhor resposta, os 'u's absolutamente não são "simplesmente despojados" em muitos contextos. Muito obrigado por isso!
— Jessica Pennell

1

Tente o seguinte:

mail_accounts [0] .encode ("ascii")


Uma resposta sem qualquer explicação é quase inútil. Por favor, tente adicionar algumas informações, como por que isso ajudaria.
— Abhilash Chandran

Pessoalmente, acho respostas longas com muita informação desnecessária que distrai. As respostas acima já explicam que o valor é unicode e precisa ser convertido para ascii, portanto não estou repetindo tudo isso. Apenas mostrando uma maneira mais simples de obter o valor. Se alguém tiver problemas para usar esta resposta, basta perguntar e fico feliz em explicar mais! Obrigado
— 2nd Sight Lab

Esta é realmente a única resposta que mostra concisamente como re-codificar cada string para 'normal' sem passar por um ciclo (o que deve ser ridiculamente ineficiente) json.loads, json.dumps.
— Ed Randall

0

Apenas substitua u por uma única citação ...

print (str.replace(mail_accounts,"u'","'"))
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.