2017-07-29 56 views
-1

我注意到json.dumps总是将字符串转换为UTF-8,我该如何防止这种情况发生?我应该自己对这些值进行编码和解码吗?这里是用例,我希望x ['a']和y ['a']是相同的。防止json.dumps转换为unicode

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'} 
+0

JSON字符串可以代表任何Unicode字符,因此使用Python的'unicode'类型是自然的选择。如果你想拥有字节(Python 2的'str'),那么根据Python的Zen,编码显然比依赖一些隐式强制要好(如第一步中'\ xc3 \ xa6'所发生的那样)。 – lenz

+0

为什么你想要'str'呢?如果只是'u'前缀烦你,那么升级到Python 3可能是最好的选择。 – lenz

+0

你会如何让''\ xc3 \ xa6''以JSON表示? JSON没有字节类型,因此您的选项可以是解码或转换为整数数组。 – lenz

回答

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不提供除对象以外的任何类型的钩子(原因可能是,最初,JSON片段的顶级结构必须是对象)。

+0

我刚刚意识到我没有仔细阅读你的问题,而你实际上是要求相反的 - 'json.dumps'中发生了什么,而不是'json.loads'。但是,这种方法仍然可以满足您对x ['a']'和'y ['a']'具有相同类型的要求。 – lenz

+0

谢谢,我很兴奋,并希望有类似的json.dumps,事实证明,设置ensure_ascii = False也无法正常工作.. –

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'} 
+0

当然,如果它是Python的两端,酸洗是自然而然的事情。 – lenz

+0

目前工作,但我希望从长远来看有更广泛的支持。我仍然希望有人能够阐明这一点。 –

+0

什么需要更多的光线?你不能同时支持Python的数据模型(='str'和'bytes'的不同类型)和广泛的支持(=支持没有这种区别的数据模型,例如JavaScript)。 – lenz