Python 跳过/删除不可解码字符
我现在正在处理一些客户输入的字符串,这些字符串是作为json的一部分。我已经把这些字符串做成了一个字典,现在我只需要做:
json.dumps(some_dict)
问题是,有些客户输入的数据似乎出现了乱码,试图把它们转成json时就会出错:
{'FIRST_NAME': 'sdffg\xed', 'LAST_NAME': 'sdfsadf'}
然后我就得到了:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xed in position 6: ordinal not in range(128)
我无法控制数据的来源,所以不能提前防止这种情况发生。既然这些坏数据已经存在了,我在想是否可以用某个占位符字符替换掉那些未知或不好的字符,或者直接删除它们。我该怎么做呢?
2 个回答
json.dumps这个函数会尝试把内容转换成ASCII格式(除非你指定了其他编码)。所以,你需要确保你的字符串能够被转换成ASCII格式。幸运的是,unicode()这个函数在没有指定编码的情况下,会把字符串自动转换成ASCII格式。所以……
copy = {}
for k, v in d.items():
copy[k] = unicode(v, errors='ignore')
json.dumps(copy)
{'FIRST_NAME': 'sdffg\xed', 'LAST_NAME': 'sdfsadf'}
这是一个Python字典,里面的键和值都是字节字符串。字节字符串在JSON中是无法表示的,因为JSON没有字节的概念。JSON中的字符串值总是Unicode格式的,所以如果想要准确地重现一个Python字典,你需要确保所有的文本键和值都是unicode
(u'...'
)字符串。
Python允许你使用'FIRST_NAME'
,因为它只包含普通的ASCII字符;大多数常见的字节编码都是ASCII的超集,所以Python可以安全地将这个字符串隐式解码为ASCII。但对于那些包含0x00到0x7F范围之外的字节的字符串,比如'sdffg\xed'
,情况就不一样了。在把它放进字典之前,你应该先用.decode
将字节str
解码为unicode
字符串。(实际上,你应该确保在整个应用程序处理中,文本数据都保持为Unicode字符串,只有在从非Unicode源加载输入时,或者输出需要发送到非Unicode目标时,才转换为字节字符串。所以在这个阶段,你不应该在字典中有字节内容。检查一下输入来源 - 你可能应该在更早的地方进行decode()
步骤。)
你可以通过以下方式解码为Unicode,并跳过或替换非ASCII字符:
>>> 'sdffg\xed'.decode('ascii', 'ignore')
u'sdffg'
>>> 'sdffg\xed'.decode('ascii', 'replace')
u'sdffg\uFFFD' # U+FFFD = �. Unicode string, json.dump can serialise OK
不过,丢掉可能有用的数据似乎有点可惜。如果你能猜到创建字节字符串时使用的编码,你可以保留那些可以恢复的非ASCII字符。如果字节0xED代表字符U+00ED(í
),那么.decode('iso-8859-1')
或者可能.decode('cp1252')
可能就是你需要的编码。