我需要做的是最好的描述为例子。 以前,我有以下代码:
content = u'<?xml version="1.0" encoding="windows-1251"?>\n' + ... #
with open(file_name, 'w') as f:
f.write(content.encode('cp1251'))
f.close;
现在我想修改整个应用程序的体系结构,并通过JSON将应该是文件内容的字符串发送到客户端,并通过javascript生成文件。
所以,现在我的代码看起来像这样:
response_data = {}
response_data['file_content'] = content.encode('cp1251')
response_data['file_name'] = file_name
return JsonResponse({'content':json.dumps(response_data, ensure_ascii=False)}) # error generated
问题是我得到UnicodeDecodeError: 'ascii' codec can't decode byte 0xd4 in position 53: ordinal not in range(128)
我也用这种方式尝试了第二个选项:
response_data = {}
response_data['file_content'] = content
response_data['file_name'] = file_name
return JsonResponse({'content':json.dumps(response_data, ensure_ascii=False).encode('utf8')}) # error generated
然后,在客户端,我尝试将utf8转换为windows-1251。
$.post ('/my_url/', data, function(response) {
var file_content = JSON.parse(response.content).file_content;
file_content = UnicodeToWin1251(file_content);
...但......我的符号扭曲了。 我知道我在这里做了一些非常错误的事情,并且很可能会把编码弄得一团糟,但是整整一天我都无法解决这个问题。有人可以暗示我的错误在哪里吗?
答案 0 :(得分:2)
XML和JSON都包含 Unicode文本的数据。 XML声明仅告诉您的XML解析器如何解码该数据的XML序列化。您手动编写序列化以匹配XML标头,您必须编码为CP-1251。
JSON标准规定所有JSON应以UTF-8,UTF-16或UTF-32编码,UTF-8为标准;再次,这只是序列化的编码。
将您的数据保留为 Unicode ,然后使用json
库将该数据编码为JSON;该库负责确保您获得UTF-8数据(在Python 2中),或者为您提供可以在以后编码为UTF-8的Unicode文本(Python 3)。然后,您的Javascript代码将再次解码JSON,此时您再次 Unicode文本:
response_data = {}
response_data['file_content'] = content
response_data['file_name'] = file_name
return JsonResponse({'content':json.dumps(response_data, ensure_ascii=False)})
这里不需要通过JSON发送二进制数据,而是发送文本。如果你的Javascript代码然后生成文件,它负责编码CP-1251,而不是你的Python代码。
如果必须将二进制数据放入JSON有效负载中,则需要将该有效负载编码为某种形式的文本。二进制数据(和CP-1251编码的文本是二进制数据)可以在文本中编码为Base-64:
import base64
response_data = {}
response_data['file_content'] = base64.encodestring(content.encode('cp1251')).decode('ascii')
response_data['file_name'] = file_name
return JsonResponse({'content':json.dumps(response_data, ensure_ascii=False)})
Base64数据被编码为仅包含ASCII数据的字节字符串,因此将其解码为JSON库的ASCII,它希望文本为Unicode文本。
现在您将以Base64文本编码包装的二进制数据发送到Javascript客户端,如果您需要二进制有效负载,现在必须对Base64进行解码。