2010-10-08 57 views
3

这是一个错误?json.dumps(pickle.dumps(u'å'))引发UnicodeDecodeError

>>> import json 
>>> import cPickle 
>>> json.dumps(cPickle.dumps(u'å')) 
Traceback (most recent call last): 
    File "<console>", line 1, in <module> 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/json/__init__.py", line 230, in dumps 
    return _default_encoder.encode(obj) 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/json/encoder.py", line 361, in encode 
    return encode_basestring_ascii(o) 
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 1-3: invalid data 

回答

5

json模块期望字符串对文本进行编码。 Pickled数据不是文本,它是8位二进制。

一个简单的解决方法,如果你真的需要通过JSON发送数据腌制,是使用BASE64:

j = json.dumps(base64.b64encode(cPickle.dumps(u'å'))) 
cPickle.loads(base64.b64decode(json.loads(j))) 

注意,这是很清楚一个Python错误。协议版本0为明确记录为ASCII,但是å作为非ASCII字节\xe5发送,而不是将其编码为"\u00E5"。这个错误在上游被报告 - 并且在错误得到修复的情况下关闭了门票。 http://bugs.python.org/issue2980

1

可能是泡菜中的一个bug。我的Python文档说(所用咸菜格式):Protocol version 0 is the original ASCII protocol and is backwards compatible with earlier versions of Python. [...] If a protocol is not specified, protocol 0 is used.


>>> cPickle.dumps(u'å').decode('ascii') 
Traceback (most recent call last): 
    File "", line 1, in 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 1: ordinal not in range(128) 

是不是没有ASCII

和,不知道是不是它的相关性,甚至一个问题:


>>> cPickle.dumps(u'å') == pickle.dumps(u'å') 
False 
0

我使用Python2.6,你的代码运行时没有任何错误。

In [1]: import json 

In [2]: import cPickle 

In [3]: json.dumps(cPickle.dumps(u'å')) 
Out[3]: '"V\\u00e5\\np1\\n."' 

顺便说一句,什么是你的系统默认编码,于我而言,这是

In [6]: sys.getdefaultencoding() 
Out[6]: 'ascii' 
+0

的错误不会在2.6.4发生我。什么补丁版本?也许封闭和假装 - 它的一个没有bug的bug在2.6以后的版本中被修正了。 – 2010-10-09 00:29:54

+0

@Glenn Maynard:我正在使用2.6.5:P – satoru 2010-10-09 00:33:41

+0

无论sys.getdefaultencoding如何,也发生在2.6.6中。 'cPickle.dumps(u'å')''返回''V \ xe5 \ n.'',而不是'V \ u00e5 \ n.''。我很好奇你为什么返回后者(这是正确的输出:完全是ASCII)。 – 2010-10-09 00:38:12