快速上手 json 库
Python 内置的 Json 库可以将 Json 对象与 Python 字典相互转换,是一个轻量、好用的库。
json 到 python
提供两种方法:json.loads() 用于将字符串格式的 Json 对象转换为 Python 对象;json.load() 用于将类文件对象(比如 .json 格式文件)的 Json 对象转换为 Python 对象。
json 类型转换到 python 的类型对照表:
| JSON数据类型 | 语法示例 | Python 解码后对应的类型 | 补充说明 |
|---|---|---|---|
| 对象(Object) | {“name”: “张三”, “age”: 25} | dict(字典) | JSON 核心复合类型,键只能是字符串 |
| 数组(Array) | [1, “test”, true, null] | list(列表) | 有序集合,可嵌套任意 JSON 类型 |
| 字符串(String) | “hello”, “2026-03-23” | str(字符串) | 支持 Unicode,需用双引号包裹 |
| 数字(Number) | 123, 3.14, -45, 1e5 | int/float(整数 / 浮点数) | JSON 无区分整数 / 浮点数,Python 自动适配 |
| 布尔值(Boolean) | true, false | bool(True/False) | 注意 JSON 是小写,Python 是大写 |
| 空值(Null) | null | None(NoneType) | JSON 唯一的空值类型 |
基本用法:
import json
# 定义一个json格式的字符串
json_data = '{"Name": "JZY", "age": 18, "address": ["HangZhou", "XiHuQu"]}'
# 转换成 python 对象
dict_data = json.loads(json_data)
print(json_data, type(json_data)) # 打印{"Name": "JZY", "age": 18, "address": ["HangZhou", "XiHuQu"]} <class 'str'>
print(dict_data, type(dict_data)) # {'Name': 'JZY', 'age': 18, 'address': ['HangZhou', 'XiHuQu']} <class 'dict'>
print(dict_data["address"], type(dict_data["address"])) # ['HangZhou', 'XiHuQu'] <class 'list'>
# 假设目录下有 data.json 文件且内容如:'{"Name": "JZY", "age": 18, "address": ["HangZhou", "XiHuQu"]}'
with open('data.json', 'r', encoding='utf-8') as f:
data = json.load(f, parse_float=Decimal)
print(json_data, type(json_data)) # 打印{"Name": "JZY", "age": 18, "address": ["HangZhou", "XiHuQu"]} <class 'str'>
print(dict_data, type(dict_data)) # {'Name': 'JZY', 'age': 18, 'address': ['HangZhou', 'XiHuQu']} <class 'dict'>
print(dict_data["address"], type(dict_data["address"])) # ['HangZhou', 'XiHuQu'] <class 'list'>自定义解码
Json 库支持多种用于自定义解码逻辑的参数,而且还可以通过它扩展对其他类型数据的支持。
parse_float、parse_int、parse_constant 用于自定义整数、浮点数和特殊常量(NaN/Infinity/-Infinity)的解析。
|
|
还有 object_pairs_hook、object_hook、cls 三个参数可用自定义编码,首先需要知道它们之间的优先级。
flowchart TD
A[开始解析JSON对象] --> B{是否指定 cls?}
B -- 是 --> C[使用自定义 JSONDecoder<br>(完全接管解码逻辑)]
B -- 否 --> D{是否指定 object_pairs_hook?}
D -- 是 --> E[调用 object_pairs_hook<br>(传入键值对列表)]
D -- 否 --> F{是否指定 object_hook?}
F -- 是 --> G[调用 object_hook<br>(传入已构建字典)]
F -- 否 --> H[返回普通 dict]
C --> I[解码结束]
E --> I
G --> I
H --> I
参数 object_hook 指定的函数于字典构建(重复键自动去除)完成后被调用,可以返回任何类型以代替字典。
|
|
参数 object_pairs_hook 指定的函数于字典构建(保留重复键)前被调用,可以返回任何类型以代替字典。
|
|
参数 cls 说是可以深度定制解码逻辑,我几乎没有用过,或许读者也用不到。这里就不介绍了,有兴趣的读者可以自行搜索用法(万能的AI)。
python 到 json
提供两种方法:json.dumps() 用于将 Python 对象转换为字符串格式的 Json 对象;json.dump() 用于将 Python 对象转换为 JSON 格式的字符串,并写入类文件对象(比如 .json 格式文件)。
python 类型转换到 json 的类型对照表:
| JSON数据类型 | 语法示例 | Python 解码后对应的类型 | 补充说明 |
|---|---|---|---|
| dict(字典) | {“name”: “张三”, “age”: 25} | 对象(Object) | JSON 核心复合类型,键只能是字符串 |
| list(列表)、tuple(元组) | [1, “test”, true, null]、(1,“2”) | 数组(Array) | 有序集合,可嵌套任意 JSON 类型 |
| str(字符串) | “hello”, “2026-03-23” | 字符串(String) | 支持 Unicode,需用双引号包裹 |
| int/float(整数 / 浮点数) | 123, 3.14, -45, 1e5 | 数字(Number) | JSON 无区分整数 |
| bool(True/False) | true, false | 布尔值(Boolean) | 注意 JSON 是小写,Python 是大写 |
| None(NoneType) | null | 空值(Null) | JSON 唯一的空值类型 |
基本用法:
import json
# 定义一个json格式的字符串
json_data = {"Name": "JZY", "age": 18, "address": ["HangZhou", "XiHuQu"]}
# 转换成 JSON 格式的字符串
dict_data = json.dumps(json_data)
print(json_data, type(json_data)) # 打印{"Name": "JZY", "age": 18, "address": ["HangZhou", "XiHuQu"]} <class 'str'>
print(dict_data, type(dict_data)) # {'Name': 'JZY', 'age': 18, 'address': ['HangZhou', 'XiHuQu']} <class 'dict'>
# 如果目录下有 data.json 文件,文件中会写入数据
with open('data.json', 'w', encoding='utf-8') as f:
json.dump(json_data, f)自定义编码
参数 default 可以接受一个函数,用于序列化不支持的 Python 对象(自定义对象、datetime对象等)。
|
|
当然还可以通过参数 cls 深度定制编码逻辑,但这里就不介绍了,有兴趣的读者可以自行搜索用法。
非法键处理
如果遇到字典中的键不是基本类型(非str, unicode, int, long, float, bool, None),设置为 True,则跳过该键值对不进行序列化,而不抛出TypeError异常;设置为 False(默认值),则抛出 TypeError 异常。
import json
# 假设我们有一个字典,其中包含非法键(元组)
data = {
'a': 1,
('b', 'c'): 2, # 元组不能作为键
'd': 3
}
try:
# 默认情况下,这将抛出TypeError
json.dumps(data)
except TypeError as e:
print("TypeError:", e) # 输出 "TypeError: keys must be str, int, float, bool or None, not tuple"
# 使用 skipkeys=True 不会抛出错误,但会丢失那些无法序列化的键值对。
json_data = json.dumps(data, skipkeys=True)
print(json_data) # 输出 "{"a": 1, "d": 3}"字符转义 ASCII
参数 ensure_ascii 设置为 True(默认值)时,非 ASCII 字符会被转义成 ASCII 字符。这确保了最大兼容性,因为 ASCII 是所有 Unicode 字符集的子集。设置为 False 时,会尽可能地输出原始字符。
|
|
循环引用检查
参数 check_circular 设置为 True(默认值),会检查对象中是否存在循环引用,即对象直接或间接地引用自己。如果发现循环引用,将抛出ValueError异常。设置为 False 时,不会进行循环引用的检查,这可以提高序列化的性能,但代价是在对象中存在循环引用时可能会导致无限递归。
|
|
格式化输出
参数 indent (默认为 None)可以将序列化后的 JSON 数据格式化以便于阅读,缩进为指定值。
|
|