Python 与 JSON 共舞
简介
在 Python 开发中,尤其是在涉及 web 开发时,不可避免会与 JSON (JavaScript Object Notation) 打交道。本文主要尝试介绍如何在 Python 中使用 JSON 。
在 Python 3 的官方文档中关于 JSON 操作的函数主要有 4 个,它们分别是 json.dump()
、 json.load()
、 json.dumps()
和json.loads()
。 json.dump()
和 json.dumps()
的功能是将 Python 对象进行编码( encoder ) ,转化为 JSON 格式;而 json.load()
和 json.loads()
则反之,对 JSON 格式对象解码( decoder ),转化为 Python 对象。
json.dump() 与 json.dumps() 的区别
json.dump()
与 json.dumps()
的作用都是把 Python 对象序列化为 JSON 格式,不同之处在哪里呢?先来看一下两者的定义:
1 | json.dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw) |
两者的定义基本相同,但是 json.dump()
多了一个 fp
参数。它们的主要区别是: json.dumps()
把 Python 对象序列化为一个 JSON 格式的字符串,而 json.dump()
则是把 Python 对象序列化为一个 JSON 格式的流,这个流可以直接写入到文件或者类似文件的对象。
听起来可能有一些拗口,下面来看个例子:
1 | >>> import json |
从上例中可以看出, json.dumps()
返回了一个 JSON 格式的字符串。
1 | >>> from pathlib import Path |
上例中的代码生成一个名为 /tmp/person.txt
的文件,其内容为: {"name": "dormouse", "age": 40}
。
json.load()
与 json.loads()
的区别与之类似。
编码
把 Python 对象序列化为 JSON 格式对象称为编码,主要使用 json.dump()
和 json.dumps()
函数。根据前文所述,这两个函数基本相同,下面主要以 json.dumps()
函数为例,json.dump()
函数的用法基本类似。
json.dumps()
用法示例:
1 | >>> import json |
编码数据类型对应规则如下表:
Python | JSON |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float, int- & float-derived Enums | number |
True | true |
False | false |
None | null |
常用参数
json.dumps()
和 json.dump()
可以使用许多参数,下面介绍几个常用的参数:
ensure_ascii 参数
该参数如默认值是 True
,在编码时,非 ASCII 字符会被转义,例如在上文的例子中,“其他”两个字被编码为 \\u5176\\u4ed6
。如果该参数设置为 Fasle
,
那么就不会转义。例如:
1 | >>> json.dumps(person, ensure_ascii=False) |
indent 参数
该参数控制编码结果的缩进,默认值是 None
。默认情况下会编码结果会紧缩在一起。如果该参数设置为一个正整数或者 \t
,那么会使编码结果具有更好的可读性。
例如:
1 | >>> print(json.dumps(person, ensure_ascii=False, indent=4)) |
sort_keys 参数
该参数控制编码结果是否按键值排序,默认值是 False
。如果该参数设置为 Ture
,那么编码结果的字典的键值会进行排序。示例:
1 | >>> print(json.dumps(person, ensure_ascii=False, indent=4, sort_keys=True)) |
更多参数请参阅:Python 3 的官方文档
解码
把 JSON 格式对象转换为 Python 对象称为解码,主要使用 json.load()
和 json.loads()
函数。这两个函数基本相同,区别类似于 json.dump()
和 json.dumps()
函数。下面主要以 json.loads()
函数为例,json.load()
函数的用法基本类似。
json.loads()
用法示例:
1 | >>> json.loads(json.dumps(person)) |
解码数据类型对应规则如下表:
JSON | Python |
---|---|
object | dict |
array | list |
string | str |
number (int) | int |
number (real) | float |
true | True |
false | False |
null | None |
自定义类型处理
有时候,我们需要处理一些自定义的类型,例如有如下这个类:
1 | class Point: |
当我们要对其实例进行编码时会产生类似如下异常(文件路径有所省略):
1 | >>> person = { |
产生异常的原因是 JSON 默认的方法无法对这种 Python 对象进行编码。那么如何解决这个问题呢?主要有两种方法:
使用函数
1 | def my_default(o): |
输出结果如下:
1 | {"name": "dormouse", "point": [1, 2]} |
使用类
1 | class MyEncoder(json.JSONEncoder): |
输出结果如下:
1 | {"name": "dormouse", "point": [1, 2]} |
参考资料
注:
本文的 Python 环境为:
Python 3.6.2 |Continuum Analytics, Inc.| (default, Jul 20 2017, 13:51:32)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux