Python 2.7.3
我已经阅读了json / dumps UnicodeDecodeError周围的所有相关线程,他们中的大多数都希望我理解我需要的编码。在我的情况下,我正在创建一个json,其中包含来自各种服务(某些p4命令行)的各种键值,可能是不同的编码。我有一张类似这样的地图
map = {"system1": some_data_from_system1, "system2", some_data_from_system2}
json.dumps(map)
抛出“UnicodeDecodeError:'ascii'编解码器无法解码位置737中的字节0x92:序数不在范围内(128)”
我想将ASCII字符偶尔转储到文件中p4 checkin / jira可能有非ascii字符,并且完全可以忽略它。我试过“ensure_ascii = False”并没有解决问题。我真正想要的是编码器在途中简单地忽略任何非ascii字符。我认为这是合理的,但找不到任何出路。
建议?
答案 0 :(得分:2)
传入时,json.dumps()
和json.dump()
函数会尝试解码字节字符串为Unicode值,默认情况下使用UTF-8:
>>> map = {"system1": '\x92'}
>>> json.dumps(map)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/json/__init__.py", line 243, in dumps
return _default_encoder.encode(obj)
File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/json/encoder.py", line 207, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/json/encoder.py", line 270, in iterencode
return _iterencode(o, 0)
UnicodeDecodeError: 'utf8' codec can't decode byte 0x92 in position 0: invalid start byte
>>> map = {"system1": u'\x92'.encode('utf8')}
>>> json.dumps(map)
'{"system1": "\\u0092"}'
您可以将encoding
关键字参数设置为对字节字符串(str
)字符使用不同的编码。
这些函数执行此操作是因为JSON是对所有字符串使用Unicode的标准。如果您将不编码为UTF-8的数据提供给它,则会失败,如上所示。
在Python 2上,输出也是一个字节字符串,编码为UTF-8。 IT可以安全地写入文件。将ensure_ascii
参数设置为False
会改变这种情况,而您将获得Unicode,这显然是您不想要的。
因此,您需要确保将放入 json.dumps()
函数的内容始终采用相同的编码,或已解码为{{1}对象。如果您不关心偶尔错过的代码点,您可以通过将错误处理程序设置为unicode
或replace
来强制执行解码:
ignore
强制解码字符串,用替换字符替换任何未被识别为ASCII码点的字节:
map = {"system1": some_data_from_system1.decode('ascii', errors='ignore')}
此处插入U+FFFD REPLACEMENT CHARACTER代码点代替未知代码点。您也可以使用>>> '\x92'.decode('ascii')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0x92 in position 0: ordinal not in range(128)
>>> '\x92'.decode('ascii', errors='replace')
u'\ufffd'
完全忽略此类字节。
答案 1 :(得分:0)
我使用了How to get string objects instead of Unicode ones from JSON in Python?和上面答案的组合来完成这段日志记录。
如上所述,some_data_from_system{1|2}
不是字符串。问题是关于一般错误记录系统。当出现问题时,您希望尽可能多地从多个子系统中转储信息以供人工检查。子系统在环境之间变化,并且当它们返回表示出错的“jsons”时,并不总是知道它们使用什么编码。为此,我从其他线程中窃取了以下方法,但本质上基本上是带有“忽略”的decode
方法
请注意 :这不是一个非常高效的方法(大多数盲目递归通常都不是)。所以这不适合典型的生产应用;根据数据,可能会遇到无限循环。但是,假设您了解免责声明,则错误记录系统 okay 。
def convert_encoding(data, encoding = 'ascii'):
if isinstance(data, dict):
return dict((convert_encoding(key), convert_encoding(value)) \
for key, value in data.iteritems())
elif isinstance(data, list):
return [convert_encoding(element) for element in data]
elif isinstance(data, unicode):
return data.encode(encoding, 'ignore')
else:
return data
map = {"system1": some_data_from_system1, "system2", some_data_from_system2}
json.dumps(convert_encoding(map), ensure_ascii = False)
完成后,这种通用方法可用于转储数据。
答案 2 :(得分:0)
如果你的json格式的字符串有非ASCII字符,你需要使用python的dump方法:
myString = "{key: 'Brazilian Portuguese has many differenct characters like maçã (apple) or Bíblia (Blible)' }" # or a map
myJSON = json.dumps(myString, encoding="latin-1") #use utf8 if appropriate
myJSON = json.loads(myJSON)