如何将汉字编码为' gbk'在json中,格式化url请求参数String?

时间:2014-10-09 04:32:26

标签: python json unicode urlencode gbk

我想将dict转储为包含一些中文字符的json String,并使用该格式设置url请求参数。

这是我的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 个答案:

答案 0 :(得分:2)

你几乎得到了ensure_ascii=False。这有效:

jsonStr = json.dumps(d, encoding='gbk', ensure_ascii=False).encode('gbk')

你需要告诉json.dumps()它将读取的字符串是GBK,并且它不应该尝试ASCII-fy它们。然后,您必须重新指定输出编码,因为json.dumps()没有单独的选项。

此解决方案类似于此处的另一个答案:https://stackoverflow.com/a/18337754/4323

所以这就是你想要的,尽管我应该注意到URI的标准似乎说它们应该尽可能使用UTF-8。有关详情,请参阅此处:https://stackoverflow.com/a/14001296/4323

答案 1 :(得分:0)

"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",编码为网址%22%5Cu4e0a%5Cu6d77%22

如果确实不希望JSON中的\u转义,您可以在URL编码之前确实ensure_ascii=False然后.encode()输出。但我不推荐它,因为你不得不担心目标应用程序在其URL参数中需要什么编码,这是一些痛苦的根源。 \u版本被所有JSON解析器接受,并且一旦进行URL编码,通常不会更长。