如何在JSON中将中文字符编码为'gbk'以格式化URL请求参数字符串?
我想把一个字典转换成包含一些中文字符的json字符串,并用这个字符串来格式化一个网址请求的参数。
这是我的Python代码:
import httplib
import simplejson as json
import urllib
d={
"key":"上海",
"num":1
}
jsonStr = json.dumps(d,encoding='gbk')
url_encode=urllib.quote_plus(jsonStr)
conn = httplib.HTTPConnection("localhost",port=8885)
conn.request("GET","/?json="+url_encode)
res = conn.getresponse()
我期望得到的请求字符串是这样的:
GET /?json=%7B%22num%22%3A+1%2C+%22key%22%3A+%22%C9%CF%BA%A3%22%7D
------------
|
V
"%C9%CF%BA%A3" represent "上海" in format of 'gbk' in url.
但是我得到的是这样的:
GET /?json=%7B%22num%22%3A+1%2C+%22key%22%3A+%22%5Cu6d93%5Cu5a43%5Cu6363%22%7D
------------------------
|
v
%5Cu6d93%5Cu5a43%5Cu6363 is 'some' format of chinese characters "上海"
我还尝试过用 ensure_ascii=False
这个选项来转换json:
jsonStr = json.dumps(d,ensure_ascii=False,encoding='gbk')
但是没有成功。
那么,我该怎么做才能让它正常工作呢?谢谢。
2 个回答
"key":"上海",
你把源代码保存为UTF-8格式,所以这就是字节字符串 '\xe4\xb8\x8a\xe6\xb5\xb7'
。
jsonStr = json.dumps(d,encoding='gbk')
JSON格式只支持Unicode字符串。你可以使用 encoding
参数来强制 json.dumps
允许字节字符串,这样它会根据给定的编码自动解码成Unicode。
但是,字节字符串的编码实际上是UTF-8,而不是 'gbk'
,所以 json.dumps
解码时出错,结果变成了 u'涓婃捣'
。这样就生成了错误的JSON输出 "\u6d93\u5a43\u6363"
,然后被URL编码成 %22%5Cu6d93%5Cu5a43%5Cu6363%22
。
要解决这个问题,你应该把传给 json.dumps
的输入改成正确的Unicode字符串(u''
):
# coding: utf-8
d = {
"key": u"上海", # or u'\u4e0a\u6d77' if you don't want to rely on the coding decl
"num":1
}
jsonStr = json.dumps(d)
...
这样你就能得到JSON "\u4e0a\u6d77"
,再编码成URL %22%5Cu4e0a%5Cu6d77%22
。
如果你 真的 不想在JSON中看到 \u
的转义字符,你可以设置 ensure_ascii=False
,然后在URL编码之前对输出进行 .encode()
。不过我不太推荐这样做,因为你需要考虑目标应用在URL参数中想要什么编码,这可能会带来一些麻烦。\u
版本被所有JSON解析器接受,并且在URL编码后通常不会长很多。
你几乎搞对了,使用 ensure_ascii=False
是正确的。这个方法可以这样用:
jsonStr = json.dumps(d, encoding='gbk', ensure_ascii=False).encode('gbk')
你需要告诉 json.dumps()
,它要处理的字符串是 GBK 编码的,并且不要试图把它们转换成 ASCII 格式。然后你还得重新指定输出的编码,因为 json.dumps()
没有单独的选项来设置这个。
这个解决方案和这里的另一个答案很相似:https://stackoverflow.com/a/18337754/4323
所以这个方法能达到你想要的效果,不过我得提醒你,关于 URI 的标准似乎建议尽可能使用 UTF-8 编码。想了解更多,可以看看这里:https://stackoverflow.com/a/14001296/4323