python2.7 json.loads() 将字符串默认解码为unicode

python2.7 中 str 与 unicode 的转换一直是个头疼的问题,在使用json模块进行序列化与反序列化时再次踩坑。

1)客户端产生一个字典格式的数据结构,其中带有一段utf-8编码的字符串

import json

raw = u"我爱中国".encode("utf-8")
send_data = {
    "id": 111,     #不重要
    "content": raw   # 数据内容为utf-8编码
}

print type(send_data['content'])    # str

2)客户端将数据进行json序列化,通过消息队列发送至服务器

send_body = json.dumps(send_data)
# send to rabbitmq

3)服务器端收到后进行解码,交给后端处理

# receive_body get from rabbitmq
receive_data = json.loads(receive_body)

4)后端使用数据,此时数据已经是unicode 而不是utf-8,再次解码会出错!

print type(receive.data['content'])   # unicode

从协议分层的角度,(1)与(4)处于同一逻辑层,抛开(2),(3)的json序列化与反序列化过程,发送与接收的数据格式应该相同,但是receive_data 与 send_data中的字符编码不一样,稍不注意使用(如按数据格式协议解码)就会出错。

查看json官方文档,发现在反序列化json.loads()的过程中会自动将所有字符串解码为unicode格式。而序列化过程json.dumps()会默认将非ascii编码的字符转换为unicode,同时可以通过参数ensure_ascii=False选择保持原有编码不变。有点绕,但是坑爹的地方就在于此,做几个实验:

1. 默认参数不变,对两种编码( utf8, unicode)进行序列化
>>> unicode_str = u"abc我爱中国def"     # u'abc\u6211\u7231\u4e2d\u56fddef'
>>> utf8_str = unicode_str.encode('utf-8')   # 'abc\xe6\x88\x91\xe7\x88\xb1\xe4\xb8\xad\xe5\x9b\xbddef'

>>> ser1 = json.dumps(unicode_str)
>>> ser2 = json.dumps(utf8_str)
>>> ser1
'"abc\\u6211\\u7231\\u4e2d\\u56fddef"'
>>> ser2
'"abc\\u6211\\u7231\\u4e2d\\u56fddef"' 

输入不同,序列化之后的结果相同!

2. 使用json.dumps(obj, ensure_ascii=False), 对两种编码进行序列化
>>> ser3 = json.dumps(unicode_str, ensure_ascii=False)
>>> ser4 = json.dumps(utf8_str, ensure_ascii=False)
>>> ser3
u'"abc\u6211\u7231\u4e2d\u56fddef"'
>>> ser4
'"abc\xe6\x88\x91\xe7\x88\xb1\xe4\xb8\xad\xe5\x9b\xbddef"'

序列化后的结果不同!分别保持了原有的编码!

3. 对上述的序列化字符串进行反序列化
>>> new1 = json.loads(ser1)
>>> new2 = json.loads(ser2)
>>> new3 = json.loads(ser3)
>>> new4 = json.loads(ser4)
>>> new1
u'abc\u6211\u7231\u4e2d\u56fddef'
>>> new2
u'abc\u6211\u7231\u4e2d\u56fddef'
>>> new3
u'abc\u6211\u7231\u4e2d\u56fddef'
>>> new4
u'abc\u6211\u7231\u4e2d\u56fddef'

四个序列化字符串反序列化结果全都相同!

结论

  1. 反序列化后总会得到unicode字符串,无论序列化阶段如何搞
  2. 序列化阶段通过参数设置,可能生成不同的序列化结果
  3. 要想少出错,在上层的数据协议里最好将字符串都定义为unicode格式
  4. 尽快转到python3
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 字符是用户可以读写的最小单位。计算机所能支持的字符组成的集合,就叫做字符集。字符集通常以二维表的形式存在。二维表的...
    刘惜有阅读 12,554评论 2 14
  • 字符集和编码简介 在编程中常常可以见到各种字符集和编码,包括ASCII,MBCS,Unicode等字符集。确切的说...
    兰山小亭阅读 12,899评论 0 13
  • 说明:本文是我在readthedocs看到的,觉得很不错所以转载过来,有删改,原文地址点这里。 实用Unicode...
    aurora阅读 4,578评论 0 6
  • 1 字符编码简介 1.1 ASCII ASCII:American Standard Code for Infor...
    hufengreborn阅读 12,645评论 3 23
  • 之前提到四月天,第一个想到的一定是林徽因,她的《你是人间的四月天》大概写了一个像初春一样美好的人。在诗里,四月是一...
    我喜欢怪人阅读 4,350评论 0 0

友情链接更多精彩内容