防止json.dumps转换为unicode

时间:2017-07-29 19:06:55

标签: json python-2.7 utf-8

我注意到json.dumps总是将字符串转换为UTF-8,我该怎样才能防止这种情况发生?我应该自己编码和解码这些值吗?这是用例,我想x ['a']和y ['a']是相同的。

x = {'a': '\xc3\xa6', 'b':u'æ', 'c':u'\xe6'}
print type(x['a']), x
 <type 'str'> {'a': '\xc3\xa6', 'c': u'\xe6', 'b': u'\xe6'}
t = json.dumps(x)
print type(t),t
 <type 'str'> {"a": "\u00e6", "c": "\u00e6", "b": "\u00e6"}
y = json.loads(t)
print type(y['a']),y
 <type 'unicode'> {u'a': u'\xe6', u'c': u'\xe6', u'b': u'\xe6'}

2 个答案:

答案 0 :(得分:0)

您可以定义一个为您执行编码的对象挂钩:

>>> x = json.dumps({'a': u'\xe6', u'b': [1, 2, 3]})
>>> x
'{"a": "\\u00e6", "b": [1, 2, 3]}'
>>> json.loads(x, object_hook=no_unicode)
{'a': '\xc3\xa6', 'b': [1, 2, 3]}

这个钩子只是用UTF-8编码所有键和(如果它们是字符串)值:

def no_unicode(obj):
    return {k.encode('utf8'): safe_encode(v)
            for k, v in obj.iteritems()}

def safe_encode(something):
    if isinstance(something, unicode):
        return something.encode('utf8')
    return something

但是,此解决方案仅适用于作为对象的直接成员的字符串。如果字符串嵌套在数组/列表中,它将无法工作:

>>> x = json.dumps({'a': [u'\xe6']})
>>> json.loads(x, object_hook=no_unicode)
{'a': [u'\xe6']}

或者如果他们处于最高级别:

>>> x = json.dumps(u'\xe6')
>>> json.loads(x, object_hook=no_unicode)
u'\xe6'

第一种情况可以通过扩展钩子以递归方式下降到容器并尝试编码遇到的任何字符串来解决。 但是,我无法找到解决第二种情况的方法。 json不为除object之外的任何类型提供钩子(原因可能是,最初JSON片段的顶级结构必须是对象)。

答案 1 :(得分:0)

无法找出另一种解决方案,我最终使用pickle来序列化我的数据结构的特定部分,然后我在json请求中发送。

x = {'a': '\xc3\xa6', 'b':u'æ', 'c':u'\xe6'}
t = pickle.dumps(x)
t = base64.b64encode(t)
print type(t),t
y = pickle.loads(base64.b64decode(t))
print type(y['a']),y

这正确打印:

<type 'str'> KGRwMApTJ2EnCnAxClMnXHhjM1x4YTYnCnAyCnNTJ2MnCnAzClbmCnA0CnNTJ2InCnA1Cmc0CnMu
<type 'str'> {'a': '\xc3\xa6', 'c': u'\xe6', 'b': u'\xe6'}