2013-09-24 108 views
4

我有以下线在我的代码为什么python json.dumps抱怨ascii解码?

outs = codecs.getwriter('utf-8')(sys.stdout) 
# dJSON contains JSON message with non-ASCII chars 
outs.write(json.dumps(dJSON,encoding='utf-8', ensure_ascii=False, indent=indent_val)) 

我得到以下异常:

outs.write(json.dumps(dJSON,encoding='utf-8', ensure_ascii=False, indent=indent_val)) 
    File "/usr/lib/python2.7/json/__init__.py", line 238, in dumps 
     **kw).encode(obj) 
    File "/usr/lib/python2.7/json/encoder.py", line 204, in encode 
     return ''.join(chunks) 
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 27: ordinal not in range(128) 

我通过由json.dumps语句中指定encoding='utf-8',我避免这类问题。为什么我仍然收到错误?

回答

6

我的猜测是,dJSON对象不包含纯unicode的,但它包含Unicode的结构和字符串已经编码为utf-8例如失败

>>> d = {u'name':u'पाइथन'.encode('utf-8')} 
>>> json.dumps(d, encoding='utf-8', ensure_ascii=False) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 238, in dumps 
    **kw).encode(obj) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/encoder.py", line 204, in encode 
    return ''.join(chunks) 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe0 in position 1: ordinal not in range(128) 

但这个工作(一切Unicode)的

>>> d = {u'name':u'पाइथन'} 
>>> json.dumps(d, encoding='utf-8', ensure_ascii=False) 
u'{"name": "\u092a\u093e\u0907\u0925\u0928"} 

虽然这也适用(所有字符串)

>>> d = {'name':u'पाइथन'.encode('utf-8')} 
>>> json.dumps(d, encoding='utf-8', ensure_ascii=False) 
'{"name": "\xe0\xa4\xaa\xe0\xa4\xbe\xe0\xa4\x87\xe0\xa4\xa5\xe0\xa4\xa8"}' 
+0

有正火'dJSON'或使用不同的选项的方式在'dumps()'中处理所有3种情况? –

+0

你可能会破解它,但我认为onus是在创建dJSON的代码上 –

3

有一种变通方法:通过utf8编码(不utf-8 !)转储方法。在这种情况下,它会强制所有字符串首先被解码为unicode,并且您可以混合使用unicode字符串和已编码为UTF-8的字符串。它为什么有效?因为在JSONEncoder源代码这样的事情:

if self.encoding != 'utf-8': 
    def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding): 
     if isinstance(o, str): 
      o = o.decode(_encoding) 
     return _orig_encoder(o) 

这正是我们所需要的,它会不会箱子的工作了。但是,当我们改变编码utf8(这是绝对相同的UTF-8作为utf-8),我们强迫这_encoder加以界定,一切工作就好:)

相关问题