Python:json.loads返回带有“u”前缀的项

172

我将从Objective-C接收一个JSON编码的字符串,并像下面的代码一样解码虚拟字符串(暂时)。我的输出每个项目前都带有字符'u':

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

JSON是如何添加这个Unicode字符的?最好的方法是什么来删除它?

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

8
Python在这里存在问题。一切都不顺利。当我试图将这些字符串写入文件时,我会在Python创建的字符串中遇到错误。例如,当Python从JSON 中取出“53”时,它将其转换为u'53'并尝试将其作为十六进制字符u'\xe1'写入文件,导致Python对一个完全好的字符串进行报错。 JSON: {"sa_BstDeAv": "53", "sa_BwVUpMx"...PYTHON: {u'sa_BstDeAv': u'53', u'sa_BwVUpMx'...写入时出错: Value error('ascii' codec can't encode character u'\xe1' in position 5: ordinal not in range(128)) - David Urry
@janehouse,这里正确的答案是jdi的答案,我真的认为你应该改变它。 - Dekel
9个回答

181

u-前缀只是表示您有一个Unicode字符串。当您真正使用字符串时,它不会出现在您的数据中。不要被打印输出所迷惑。

例如,请尝试以下内容:

print mail_accounts[0]["i"]

你不会看到字母 u。


6
你的回答是我得到的最有用的,我认为这个问题的提问者会非常感激:https://dev59.com/13NA5IYBdhLWcg3wcddk - jimh
1
非常感谢!我对于“u''”这个字母困惑了很长时间。 - ketan khandagale
1
除非你复制粘贴,否则你的数据中会有大量的u。坦白地说,打印一个u来表示它是Unicode字符串是关于Python的最糟糕的错误之一。完全荒谬。如果是ASCII,为什么不在每个字符串前面打印一个a?如果是整数,为什么不打印一个i - Snowcrash
在Python 2中,Unicode字符串是一种不同于字节字符串的类型,因此数据的repr包括前缀以指示它。这与内容无关,而与类型有关。如果您将内容粘贴回Python程序,则u前缀是可以接受的。如果不是,则可能希望改用json.dumps()。 - Ned Batchelder
你必须使用字符串来搜索JSON字典,但是不能使用点运算符。 - CDM social medias in bio
“u” 对最终用户来说并不是一件好事,会让他们感到困惑,我不想展示它。 - Ed Randall

161

如果直接打印JSON对象,你会得到Python在该地址的内存反刍,这是无效的JSON,因为它前缀为u。因此,请使用print(json.dumps(s))来告诉JSON解析器呈现有效的JSON。巴辛嘎。 - Eric Leschinski

59

下面的d3打印结果是您要查找的(它是dumps和loads的组合):)

具有:

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

输出:

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
哦?json.dumps将字典转换回(JSON编码的)字符串。这不是原帖想要做的。-1。 - Mark Amery
10
但是如果你将它与json.loads一起使用,它会输出不带编码字符的字典,这就是问题的答案(这是上面d3打印的内容),请仔细阅读答案! - Mercury

13

在一个对象后添加'U'字符表示该对象是以Unicode编码的。

如果你想从你的对象中删除那些'u'字符,你可以这样做:

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

让我们从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'}]

我建议每个新手都试试这个脚本,然后你就有一个可以将JSON输出转换的脚本了 :) ... 如果只需在脚本中添加stdin和json格式,你就可以开始使用了! - Jordan Gee

10

Unicode是这里适当的类型。JSONDecoder文档描述了转换表,并说明JSON字符串对象被解码为Unicode对象。

来自18.2.2. 编码器和解码器

Unicode是这里适当的类型。JSONDecoder文档描述了转换表,并说明JSON字符串对象被解码为Unicode对象。

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

"编码方式决定了该实例解码的任何str对象的解释所使用的编码方式(默认为UTF-8)."


8

u前缀表示这些字符串是Unicode而不是8位字符串。最好的方法是切换到Python 3,其中默认情况下字符串为Unicode,这样就不会显示u前缀。如果这不是一个选择,那么str构造函数将从Unicode转换为8位,因此只需递归地循环遍历结果并将unicode转换为str即可。然而,最好还是将字符串保留为Unicode。


5
当我尝试使用Python的logging库来捕获JSON数据进行调试和故障排除时,遇到了这个问题。当你想将文本复制并粘贴到你的代码中时,获取字符“u”会很麻烦。
像大家所说的那样,这是因为它是一个Unicode表示,可能是因为你首先使用json.loads()从字符串中加载数据。如果你想在日志中获得JSON表示形式,而没有前缀“u”,方法是在记录日志之前使用json.dumps()。例如:
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
这真的应该是最好的答案,在许多情况下,'u'绝对不会“只是被剥离掉”。非常感谢您! - Jessica Pennell

2

试试这个:

mail_accounts[0].encode("ascii")

1
一个没有任何解释的答案几乎是无用的。请尝试添加一些信息,比如为什么这会有帮助。 - Abhilash Chandran
就我个人而言,我发现过长的答案含有太多不必要的信息,会分散注意力。上面的答案已经解释了该值是Unicode并需要转换为ASCII,所以我不会重复所有这些内容。只是展示了一种更简单的获取该值的方法。如果有人在使用这个答案时遇到问题,请随时询问,我很乐意进一步解释!谢谢。 - 2nd Sight Lab
1
这实际上是唯一一个简洁地展示如何重新编码每个字符串为“正常”而不经过(必须非常低效的)json.loads,json.dumps循环的答案。 - Ed Randall
1
你所忽略的是,如果消息包含任何非ASCII字符,这将会因UnicodeEncodeError而彻底失败。你可以通过使用errors="ignore"来防止这种情况发生,但更常见的问题是你不知道自己在做什么,而且忽略错误只是把这个事实藏在地毯下。太多时候,“我想要ASCII”只是加密术语,意思是“我不理解英语以外的语言;我希望它们消失;但同时我会编写对其他语言(通常是不必要的)工作不良的软件。” - tripleee

-3

只需将u'替换为单引号即可...

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

那会如何有所帮助? - Peter Mortensen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接