将 JSON 中的 "windows-1251" 编码字符串从 python 发送到 javascript
Sending "windows-1251"-encoded string in JSON from python to javascript
最好将我需要做的作为示例进行描述。
以前,我有以下代码:
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);
...但是...我得到了扭曲的符号。
我知道我在这里做错了一些事情,很可能会把编码搞砸,但我仍然整整一天都无法解决这个问题。有人可以提示我的错误在哪里吗?
XML 和 JSON 都包含 Unicode 文本 的数据。 XML 声明仅告诉您的 XML 解析器如何解码该数据的 XML 序列化。您手动编写序列化以匹配 XML header,您必须编码为 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 文本。
现在您正在向 Javascript 客户端发送封装在 Base64 文本编码中的二进制数据,如果您在那里需要二进制负载,客户端现在必须解码 Base64。
最好将我需要做的作为示例进行描述。 以前,我有以下代码:
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);
...但是...我得到了扭曲的符号。 我知道我在这里做错了一些事情,很可能会把编码搞砸,但我仍然整整一天都无法解决这个问题。有人可以提示我的错误在哪里吗?
XML 和 JSON 都包含 Unicode 文本 的数据。 XML 声明仅告诉您的 XML 解析器如何解码该数据的 XML 序列化。您手动编写序列化以匹配 XML header,您必须编码为 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 文本。
现在您正在向 Javascript 客户端发送封装在 Base64 文本编码中的二进制数据,如果您在那里需要二进制负载,客户端现在必须解码 Base64。