快捷搜索:  汽车  科技

pythonjson详细教程(这么详细的实例讲解)

pythonjson详细教程(这么详细的实例讲解)有了前面的铺垫 就可以来说说 json.dumps 了. 下面以一个例子展开: '{0:04x}'.format(20013)使用 json.dumps获取字符 Unicode 码点标准库提供了 ord 函数输出一个字符的 Unicode 码点 使用 chr 函数将 码点 转换成 字符 下面是示例:输出的 码点 是使用 十进制 表示的 可以使用以下代码将整数格式化成十六进制字符串:

今天为大家带来的内容是:这么详细的实例讲解,不多了(Python在使用json时需要注意的编码)

写这篇文章的缘由是我使用 reqeusts 库请求接口的时候,直接使用请求参数里的 json 字段发送数据,但是服务器无法识别我发送的数据,排查了好久才知道 requests 内部是使用 json.dumps 将字符串转成 json 的 ,而 json.dumps 默认情况下会将 非ASCII 字符转义,也就是我发送数据中的中文被转义了 所以服务器无法识别,这篇文章虽然是 json.dumps 问题的总结, 但也会涉及到 字符编码 问题 所以就简单先说一下 字符编码。

Python 中的字符编码

在 python3 中 字符 在内存中是使用 Unicode 存储的 常规的字符使用 两个字节 表示 一些很生僻的字符就需要 四个字节. 默认使用 Unicode 存储是什么意思呢 那就是例子来解释一下 在 Python Shell 中输入以下字符串 '\u4e2d\u6587' 观察其输出:

pythonjson详细教程(这么详细的实例讲解)(1)

输出的为 中文 两个字. 其实 \u4e2d 和 \u6587 分别表示 中 和 文 的 Unicode 编码(术语称为 码点)的 十六进制 表示 在 Python3 中以 \u 开头的字符串被解析为 Unicode 字符 然后通过其十六进制 码点 解析出具体的字符 所以 中文 的内存表示即为 \u4e2d\u6587

获取字符 Unicode 码点

标准库提供了 ord 函数输出一个字符的 Unicode 码点 使用 chr 函数将 码点 转换成 字符 下面是示例:

pythonjson详细教程(这么详细的实例讲解)(2)

嗨喽:正在学习python的小伙伴或者打算学习的,可以私信小编“07”领取资料!

输出的 码点 是使用 十进制 表示的 可以使用以下代码将整数格式化成十六进制字符串:

'{0:04x}'.format(20013)

使用 json.dumps

有了前面的铺垫 就可以来说说 json.dumps 了. 下面以一个例子展开:

pythonjson详细教程(这么详细的实例讲解)(3)

可以看到,在 ensure_ascii 为 True 的情况下 中文 被编码成了 Unicode 码 为 False 才能正常显示 但是这跟 ASCII 有什么关系呢? 来看一下官方文档 对这个参数的解释:

如果 ensure_ascii 是 true (即默认值),输出保证将所有输入的非 ASCII 字符转义。如果 ensure_ascii 是 false,这些字符会原样输出。

现在稍微明白了 在 ensure_ascii 为 True 的情况下 如果字符串中存在 非ASCII 字符就将其转义 根据结果可以知道这个字符被转义为 Unicode 码并格式化成了一个字符串 注意 "\\u4e2d\\u6587" 与 "\u4e2d\\u6587" 是不同的 前者是长度为 12 的字符串 后者会被 Python 直接解析为 中文 长度为 2. 这也就是我一开始出现的问题 直接将转义的字符串在网络上传输可能会无法被识别. 比如 中文 被转义成 \\u4e2d\\u6587 而服务器如果不知道它是被转义过的字符串 那它就是一个长度为 12 的普通字符串 肯定会识别出错. 而将 ensure_ascii 设为 False 就不会进行转义 使用原始字符.

识别转义字符

如果服务器收到数据后发现是被转化过的 那怎么识别呢? 其实被转义字符串与使用 unicode_escape 对字符串进行编码再使用 utf-8 进行解码的结果一致 代码如下:

pythonjson详细教程(这么详细的实例讲解)(4)

所以识别只要反过来使用 utf-8 编码再使用 unicode_escape 解码就可以了。

转义是如何进行的

现在来看一下 json 到底是怎么对字符进行转义的. 在 json.dumps 源码中仔细调试的话会发现 它调用的是 JSONEncoder.encode 方法 而 encode 中的代码片段如下:

pythonjson详细教程(这么详细的实例讲解)(5)

它会根据 ensure_ascii 的值选择调用函数. 而 encode_basestring_ascii 的值是 (c_encode_basestring_ascii or py_encode_basestring_ascii) 也就是默认是用 C 实现的版本 其次使用 Python 实现的版本 既然有 Python 版本 当然要看一下是怎么实现的 py_encode_basestring_ascii 可以直接使用 from json.encoder import py_encode_basestring_ascii 导入 直接在其内部就可以调试. 下面是其源码:

pythonjson详细教程(这么详细的实例讲解)(6)

嗨喽:正在学习python的小伙伴或者打算学习的,可以私信小编“07”领取资料!

从最后的 return 可以看到它实际上是 正则替换 最后在前后添加 双引号. ESCAPE_ASCII 的定义如下:

ESCAPE_ASCII = re.compile(r'([\\"]|[^\ -~])')

其中 ([\\"] 用于匹配 \\ 和 " 而 [^\ -~] 表示 \ -~ 取反(这里的反斜杠貌似是对空格进行转义 我不是很理解 不进行转义依旧可以匹配到) 在 ASCII 表里 空格字符 对应十进制是 40 ~ 是 176 这是所有的可打印字符 取反就是所有编码不在 40 ~ 176 的字符 所以中文就会被匹配到 下面为 ASCII表:

pythonjson详细教程(这么详细的实例讲解)(7)

嗨喽:正在学习python的小伙伴或者打算学习的,可以私信小编“07”领取资料!

对于匹配到的字符 会传入回调函数 replace 做转义. replace 函数中的 ESCAPE_DCT 为:

pythonjson详细教程(这么详细的实例讲解)(8)

会对常用字符进行转义 如果失败就获取它的 Unicode 码点 然后判断是否为小于 0x10000 即是否为 两字节 字符(两字节最大为0xFFFF) 如果是就格式化为 Unicode 码 如果不是就使用 四字节 表示.

总结:

记得使用 requests 发送 JSON 数据时将中文编码,以上就是本文的全部内容,希望对大家的学习有所帮助。

最后多说一句,小编是一名python开发工程师,这里有我自己整理了一套最新的python系统学习教程,包括从基础的python脚本到web开发、爬虫、数据分析、数据可视化、机器学习等。想要这些资料的可以关注小编,并在后台私信小编:“07”即可领取。

猜您喜欢: